X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffatal-signal.c;h=64b346d8747b4637bcc684bc74a706ad8445e2e6;hb=b6d87f536521a59758453d8dbd071e7cd6efc39d;hp=7654d1f4f2286ec993316bd93b5313630e32e865;hpb=640cd5a77a3e334811fe60f6bbc0ae215854b91a;p=gnulib.git diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index 7654d1f4f..64b346d87 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -26,11 +26,11 @@ #include #include +#include "sig-handler.h" #include "xalloc.h" #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) - /* ========================================================================= */ @@ -88,7 +88,6 @@ init_fatal_signals (void) static bool fatal_signals_initialized = false; if (!fatal_signals_initialized) { -#if HAVE_SIGACTION size_t i; for (i = 0; i < num_fatal_signals; i++) @@ -96,14 +95,9 @@ init_fatal_signals (void) struct sigaction action; if (sigaction (fatal_signals[i], NULL, &action) >= 0 - /* POSIX says that SIG_IGN can only occur when action.sa_flags - does not contain SA_SIGINFO. But in Linux 2.4, for example, - SA_SIGINFO can actually be set and is ignored when sa_handler - is SIG_IGN. So don't bother testing for SA_SIGINFO. */ - && action.sa_handler == SIG_IGN) + && get_handler (&action) == SIG_IGN) fatal_signals[i] = -1; } -#endif fatal_signals_initialized = true; } @@ -136,10 +130,14 @@ static inline void uninstall_handlers () { size_t i; + struct sigaction action; + action.sa_handler = SIG_DFL; + action.sa_flags = 0; + sigemptyset (&action.sa_mask); for (i = 0; i < num_fatal_signals; i++) if (fatal_signals[i] >= 0) - signal (fatal_signals[i], SIG_DFL); + sigaction (fatal_signals[i], &action, NULL); } @@ -162,9 +160,10 @@ fatal_signal_handler (int sig) } /* Now execute the signal's default action. - If signal() blocks the signal being delivered for the duration of the - signal handler's execution, the re-raised signal is delivered when this - handler returns; otherwise it is delivered already during raise(). */ + If the signal being delivered was blocked, the re-raised signal would be + delivered when this handler returns. But the way we install this handler, + no signal is blocked, and the re-raised signal is delivered already + during raise(). */ uninstall_handlers (); raise (sig); } @@ -175,10 +174,17 @@ static inline void install_handlers () { size_t i; - + struct sigaction action; + + action.sa_handler = &fatal_signal_handler; + /* If we get a fatal signal while executing fatal_signal_handler, enter + fatal_signal_handler recursively, since it is reentrant. Hence no + SA_RESETHAND. */ + action.sa_flags = SA_NODEFER; + sigemptyset (&action.sa_mask); for (i = 0; i < num_fatal_signals; i++) if (fatal_signals[i] >= 0) - signal (fatal_signals[i], &fatal_signal_handler); + sigaction (fatal_signals[i], &action, NULL); }