Add ability to run fatal signal hooks upon normal termination too.
authorBen Pfaff <blp@nicira.com>
Wed, 27 Aug 2008 18:29:45 +0000 (11:29 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 28 Aug 2008 21:24:39 +0000 (14:24 -0700)
This is convenient since in many cases we want these hooks to run in
both cases.

include/fatal-signal.h
lib/fatal-signal.c
lib/netdev.c
tests/test-dhcp-client.c
utilities/ofp-discover.c

index c45c117..ff7ad63 100644 (file)
 #ifndef FATAL_SIGNAL_H
 #define FATAL_SIGNAL_H 1
 
+#include <stdbool.h>
+
 /* Basic interface. */
-void fatal_signal_add_hook(void (*)(void *aux), void *aux);
+void fatal_signal_add_hook(void (*)(void *aux), void *aux, bool run_at_exit);
 void fatal_signal_block(void);
 void fatal_signal_unblock(void);
 void fatal_signal_fork(void);
index d299cdf..95f54ff 100644 (file)
@@ -52,6 +52,7 @@ static sigset_t fatal_signal_set;
 struct hook {
     void (*func)(void *aux);
     void *aux;
+    bool run_at_exit;
 };
 #define MAX_HOOKS 32
 static struct hook hooks[MAX_HOOKS];
@@ -64,16 +65,20 @@ static int block_level = 0;
 static sigset_t saved_signal_mask;
 
 static void call_sigprocmask(int how, sigset_t* new_set, sigset_t* old_set);
+static void atexit_handler(void);
+static void call_hooks(int sig_nr);
 
-/* Registers 'hook' to be called when a process termination signal is
- * raised. */
+/* Registers 'hook' to be called when a process termination signal is raised.
+ * If 'run_at_exit' is true, 'hook' is also called during normal process
+ * termination, e.g. when exit() is called or when main() returns. */
 void
-fatal_signal_add_hook(void (*func)(void *aux), void *aux)
+fatal_signal_add_hook(void (*func)(void *aux), void *aux, bool run_at_exit)
 {
     fatal_signal_block();
     assert(n_hooks < MAX_HOOKS);
     hooks[n_hooks].func = func;
     hooks[n_hooks].aux = aux;
+    hooks[n_hooks].run_at_exit = run_at_exit;
     n_hooks++;
     fatal_signal_unblock();
 }
@@ -107,6 +112,7 @@ fatal_signal_block()
                 fatal(errno, "signal");
             }
         }
+        atexit(atexit_handler);
     }
 
     if (++block_level == 1) {
@@ -138,6 +144,23 @@ fatal_signal_unblock()
  * handler in the case where the signal has its default handling.)  */
 void
 fatal_signal_handler(int sig_nr)
+{
+    call_hooks(sig_nr);
+
+    /* Re-raise the signal with the default handling so that the program
+     * termination status reflects that we were killed by this signal */
+    signal(sig_nr, SIG_DFL);
+    raise(sig_nr);
+}
+
+static void
+atexit_handler(void)
+{
+    call_hooks(0);
+}
+
+static void
+call_hooks(int sig_nr)
 {
     volatile sig_atomic_t recurse = 0;
     if (!recurse) {
@@ -145,16 +168,13 @@ fatal_signal_handler(int sig_nr)
 
         recurse = 1;
 
-        /* Call all the hooks. */
         for (i = 0; i < n_hooks; i++) {
-            hooks[i].func(hooks[i].aux);
+            struct hook *h = &hooks[i];
+            if (sig_nr || h->run_at_exit) {
+                h->func(h->aux);
+            }
         }
     }
-
-    /* Re-raise the signal with the default handling so that the program
-     * termination status reflects that we were killed by this signal */
-    signal(sig_nr, SIG_DFL);
-    raise(sig_nr);
 }
 \f
 static char **files;
@@ -172,8 +192,7 @@ fatal_signal_add_file_to_unlink(const char *file)
     static bool added_hook = false;
     if (!added_hook) {
         added_hook = true;
-        fatal_signal_add_hook(unlink_files, NULL);
-        atexit(do_unlink_files);
+        fatal_signal_add_hook(unlink_files, NULL, true);
     }
 
     fatal_signal_block();
index 581b362..fc19294 100644 (file)
@@ -770,7 +770,7 @@ init_netdev(void)
     static bool inited;
     if (!inited) {
         inited = true;
-        fatal_signal_add_hook(restore_all_flags, NULL);
+        fatal_signal_add_hook(restore_all_flags, NULL, true);
         af_inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
         if (af_inet_sock < 0) {
             fatal(errno, "socket(AF_INET)");
index 285d99f..163c59f 100644 (file)
@@ -84,7 +84,7 @@ main(int argc, char *argv[])
         fatal(error, "dhclient_create failed");
     }
     dhclient_init(cli, request_ip.s_addr);
-    fatal_signal_add_hook(release, cli);
+    fatal_signal_add_hook(release, cli, true);
 
     for (;;) {
         fatal_signal_block();
index 646aec5..a30d357 100644 (file)
@@ -117,7 +117,7 @@ main(int argc, char *argv[])
         struct iface *iface = &ifaces[i];
         dhclient_init(iface->dhcp, 0);
     }
-    fatal_signal_add_hook(release_ifaces, NULL);
+    fatal_signal_add_hook(release_ifaces, NULL, true);
 
     retval = regcomp(&accept_controller_regex, accept_controller_re,
                      REG_NOSUB | REG_EXTENDED);