summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGuillem Jover <guillem@debian.org>2010-10-16 19:04:13 +0200
committerGuillem Jover <guillem@debian.org>2010-11-19 05:21:13 +0100
commitbf1455085899a5203373eff34741cd7ea3d64774 (patch)
tree5196b2f07946c4343fcb9e25f005703e7519a466 /lib
parente07774f1b528754ec5161af245d801158f0d4dd2 (diff)
downloaddpkg-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.c53
-rw-r--r--lib/dpkg/ehandle.h9
-rw-r--r--lib/dpkg/libdpkg.Versions3
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;