Просмотр исходного кода

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.
Guillem Jover лет назад: 15
Родитель
Сommit
bf14550858
3 измененных файлов с 56 добавлено и 9 удалено
  1. 47 6
      lib/dpkg/ehandle.c
  2. 7 2
      lib/dpkg/ehandle.h
  3. 2 1
      lib/dpkg/libdpkg.Versions

+ 47 - 6
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);
         }

+ 7 - 2
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);
 

+ 2 - 1
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;