X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffatal-signal.c;h=df9e0116b1bee71f34dd95382b3906a36e407258;hb=1a2869593e115e4a6c74aaa0b23ca612357403ce;hp=eca46dba0c69fcf0d642b676b2caa35337e03890;hpb=4b2f21b36a615728ebf2a0e1bc2c8def175703a8;p=gnulib.git diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index eca46dba0..df9e0116b 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -125,19 +125,25 @@ static sig_atomic_t volatile actions_count = 0; static size_t actions_allocated = SIZEOF (static_actions); +/* The saved signal handlers. + Size 32 would not be sufficient: On HP-UX, SIGXCPU = 33, SIGXFSZ = 34. */ +static struct sigaction saved_sigactions[64]; + + /* Uninstall the handlers. */ 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) - sigaction (fatal_signals[i], &action, NULL); + { + int sig = fatal_signals[i]; + if (saved_sigactions[sig].sa_handler == SIG_IGN) + saved_sigactions[sig].sa_handler = SIG_DFL; + sigaction (sig, &saved_sigactions[sig], NULL); + } } @@ -160,9 +166,10 @@ fatal_signal_handler (int sig) } /* Now execute the signal's default action. - If any cleanup action blocks the signal that triggered the cleanup, 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); } @@ -176,13 +183,20 @@ install_handlers () struct sigaction action; action.sa_handler = &fatal_signal_handler; - /* One-shot handling - if we fault while handling a fault, the - cleanup actions are intentionally cut short. */ - action.sa_flags = SA_NODEFER | SA_RESETHAND; + /* 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) - sigaction (fatal_signals[i], &action, NULL); + { + int sig = fatal_signals[i]; + + if (!(sig < sizeof (saved_sigactions) / sizeof (saved_sigactions[0]))) + abort (); + sigaction (sig, &action, &saved_sigactions[sig]); + } }