From b67da66b07a77d9bd67926f83c5ae7aa57f1dba9 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 12 Aug 2008 14:24:10 -0700 Subject: [PATCH] Make fatal-signal more willing to share signals with other handlers. --- include/fatal-signal.h | 4 +++ lib/fatal-signal.c | 62 ++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/include/fatal-signal.h b/include/fatal-signal.h index 39d86fd51..c45c11728 100644 --- a/include/fatal-signal.h +++ b/include/fatal-signal.h @@ -47,4 +47,8 @@ void fatal_signal_fork(void); void fatal_signal_add_file_to_unlink(const char *); void fatal_signal_remove_file_to_unlink(const char *); +/* Interface for other code that catches one of our signals and needs to pass + * it through. */ +void fatal_signal_handler(int sig_nr); + #endif /* fatal-signal.h */ diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index fe1f52b2d..d299cdfd2 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -64,7 +64,6 @@ 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 signal_handler(int sig_nr); /* Registers 'hook' to be called when a process termination signal is * raised. */ @@ -97,9 +96,15 @@ fatal_signal_block() sigemptyset(&fatal_signal_set); for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) { int sig_nr = fatal_signals[i]; + struct sigaction old_sa; + sigaddset(&fatal_signal_set, sig_nr); - if (signal(sig_nr, signal_handler) == SIG_IGN) { - signal(sig_nr, SIG_IGN); + if (sigaction(sig_nr, NULL, &old_sa)) { + fatal(errno, "sigaction"); + } + if (old_sa.sa_handler == SIG_DFL + && signal(sig_nr, fatal_signal_handler) == SIG_ERR) { + fatal(errno, "signal"); } } } @@ -121,6 +126,36 @@ fatal_signal_unblock() call_sigprocmask(SIG_SETMASK, &saved_signal_mask, NULL); } } + +/* Handles fatal signal number 'sig_nr'. + * + * Ordinarily this is the actual signal handler. When other code needs to + * handle one of our signals, however, it can register for that signal and, if + * and when necessary, call this function to do fatal signal processing for it + * and terminate the process. Currently only timeval.c does this, for SIGALRM. + * (It is not important whether the other code sets up its signal handler + * before or after this file, because this file will only set up a signal + * handler in the case where the signal has its default handling.) */ +void +fatal_signal_handler(int sig_nr) +{ + volatile sig_atomic_t recurse = 0; + if (!recurse) { + size_t i; + + recurse = 1; + + /* Call all the hooks. */ + for (i = 0; i < n_hooks; i++) { + hooks[i].func(hooks[i].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; static size_t n_files, max_files; @@ -213,24 +248,3 @@ call_sigprocmask(int how, sigset_t* new_set, sigset_t* old_set) fprintf(stderr, "sigprocmask: %s\n", strerror(errno)); } } - -static void -signal_handler(int sig_nr) -{ - volatile sig_atomic_t recurse = 0; - if (!recurse) { - size_t i; - - recurse = 1; - - /* Call all the hooks. */ - for (i = 0; i < n_hooks; i++) { - hooks[i].func(hooks[i].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); -} -- 2.43.0