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.
This commit is contained in:
1 parent
7129a314b2
commit
3cc1ae6a32
5 files changed
+37
-16
No files matched your search
@@ -34,8 +34,10 @@
|
||||
#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);
|
||||
|
||||
+31
-12
@@ -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();
|
||||
|
||||
+1
-1
@@ -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)");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user