From: Ben Pfaff Date: Wed, 27 Aug 2008 18:29:45 +0000 (-0700) Subject: Add ability to run fatal signal hooks upon normal termination too. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3cc1ae6a32572e58b46dfdf8c0d1a7c00f01f22f;p=openvswitch Add ability to run fatal signal hooks upon normal termination too. This is convenient since in many cases we want these hooks to run in both cases. --- diff --git a/include/fatal-signal.h b/include/fatal-signal.h index c45c1172..ff7ad63d 100644 --- a/include/fatal-signal.h +++ b/include/fatal-signal.h @@ -34,8 +34,10 @@ #ifndef FATAL_SIGNAL_H #define FATAL_SIGNAL_H 1 +#include + /* 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); diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index d299cdfd..95f54ff9 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -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); } 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(); diff --git a/lib/netdev.c b/lib/netdev.c index 581b362a..fc192948 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -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)"); diff --git a/tests/test-dhcp-client.c b/tests/test-dhcp-client.c index 285d99fb..163c59f9 100644 --- a/tests/test-dhcp-client.c +++ b/tests/test-dhcp-client.c @@ -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(); diff --git a/utilities/ofp-discover.c b/utilities/ofp-discover.c index 646aec50..a30d357f 100644 --- a/utilities/ofp-discover.c +++ b/utilities/ofp-discover.c @@ -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);