diff options
author | Guillem Jover <guillem@debian.org> | 2010-10-16 19:04:13 +0200 |
---|---|---|
committer | Guillem Jover <guillem@debian.org> | 2010-11-19 05:21:13 +0100 |
commit | bf1455085899a5203373eff34741cd7ea3d64774 (patch) | |
tree | 5196b2f07946c4343fcb9e25f005703e7519a466 /lib | |
parent | e07774f1b528754ec5161af245d801158f0d4dd2 (diff) | |
download | dpkg-bf1455085899a5203373eff34741cd7ea3d64774.tar.gz |
libdpkg: Add error context function handler support
This allows the code to use a function instead of a jump buffer to
handle the errors, which happen to be possible for the general case,
when it does not need to continue processing in an upper stack frame.
Thus reducing the preceived complexity of simple code, and avoids
exposing setjmp machinery to the casual user.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/dpkg/ehandle.c | 53 | ||||
-rw-r--r-- | lib/dpkg/ehandle.h | 9 | ||||
-rw-r--r-- | lib/dpkg/libdpkg.Versions | 3 |
3 files changed, 56 insertions, 9 deletions
diff --git a/lib/dpkg/ehandle.c b/lib/dpkg/ehandle.c index b630bf504..9e15161a8 100644 --- a/lib/dpkg/ehandle.c +++ b/lib/dpkg/ehandle.c @@ -62,7 +62,17 @@ struct cleanup_entry { struct error_context { struct error_context *next; - jmp_buf *jump; + + enum { + handler_type_func, + handler_type_jump, + } handler_type; + + union { + error_handler *func; + jmp_buf *jump; + } handler; + struct cleanup_entry *cleanups; void (*printerror)(const char *emsg, const char *contextstring); const char *contextstring; @@ -103,8 +113,13 @@ run_error_handler(void) fprintf(stderr, _("%s: outside error context, aborting:\n %s\n"), thisname, errmsg); exit(2); + } else if (econtext->handler_type == handler_type_func) { + econtext->handler.func(); + internerr("error handler returned unexpectedly!"); + } else if (econtext->handler_type == handler_type_jump) { + longjmp(*econtext->handler.jump, 1); } else { - longjmp(*econtext->jump, 1); + internerr("unknown error handler type %d!", econtext->handler_type); } } @@ -131,15 +146,41 @@ set_error_printer(struct error_context *ec, error_printer *printerror, ec->contextstring = contextstring; } +static void +set_func_handler(struct error_context *ec, error_handler *func) +{ + ec->handler_type = handler_type_func; + ec->handler.func = func; +} + +static void +set_jump_handler(struct error_context *ec, jmp_buf *jump) +{ + ec->handler_type = handler_type_jump; + ec->handler.jump = jump; +} + +void +push_error_context_func(error_handler *func, error_printer *printerror, + const char *contextstring) +{ + struct error_context *ec; + + ec = error_context_new(); + set_error_printer(ec, printerror, contextstring); + set_func_handler(ec, func); + onerr_abort = 0; +} + void -push_error_handler(jmp_buf *jump, error_printer *printerror, - const char *contextstring) +push_error_context_jump(jmp_buf *jump, error_printer *printerror, + const char *contextstring) { struct error_context *ec; ec = error_context_new(); set_error_printer(ec, printerror, contextstring); - ec->jump = jump; + set_jump_handler(ec, jump); onerr_abort = 0; } @@ -177,10 +218,10 @@ run_cleanups(struct error_context *econ, int flagsetin) if (setjmp(recurse_jump)) { run_cleanups(&recurserr, ehflag_bombout | ehflag_recursiveerror); } else { - recurserr.jump = &recurse_jump; recurserr.cleanups= NULL; recurserr.next= NULL; set_error_printer(&recurserr, print_cleanup_error, NULL); + set_jump_handler(&recurserr, &recurse_jump); econtext= &recurserr; cep->calls[i].call(cep->argc,cep->argv); } diff --git a/lib/dpkg/ehandle.h b/lib/dpkg/ehandle.h index d86ccaf96..1b72700a2 100644 --- a/lib/dpkg/ehandle.h +++ b/lib/dpkg/ehandle.h @@ -40,13 +40,18 @@ enum { ehflag_recursiveerror = 04 }; +typedef void error_handler(void); typedef void error_printer(const char *emsg, const char *contextstring); void print_fatal_error(const char *emsg, const char *contextstring); void catch_fatal_error(void); -void push_error_handler(jmp_buf *jbufp, error_printer *printerror, - const char *contextstring); +#define push_error_handler push_error_context_jump + +void push_error_context_jump(jmp_buf *jbufp, error_printer *printerror, + const char *contextstring); +void push_error_context_func(error_handler *func, error_printer *printerror, + const char *contextstring); void error_unwind(int flagset); void set_error_display(error_printer *printerror, const char *contextstring); diff --git a/lib/dpkg/libdpkg.Versions b/lib/dpkg/libdpkg.Versions index 1e9a25d66..0850328ad 100644 --- a/lib/dpkg/libdpkg.Versions +++ b/lib/dpkg/libdpkg.Versions @@ -9,10 +9,11 @@ local: LIBDPKG_PRIVATE { # Error handling + push_error_context_jump; + push_error_context_func; set_error_display; print_fatal_error; catch_fatal_error; - push_error_handler; push_checkpoint; push_cleanup; pop_cleanup; |