diff options
Diffstat (limited to 'src/sighook.c')
-rw-r--r-- | src/sighook.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/src/sighook.c b/src/sighook.c index cd17e42..a294206 100644 --- a/src/sighook.c +++ b/src/sighook.c @@ -425,13 +425,19 @@ static enum sigflags run_hooks(struct siglist *list, int sig, siginfo_t *info) { /** Dispatches a signal to the registered handlers. */ static void sigdispatch(int sig, siginfo_t *info, void *context) { - // https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03_03 + // If we get a fault (e.g. a "real" SIGSEGV, not something like + // kill(..., SIGSEGV)), don't try to run signal hooks, since we could be + // in an arbitrarily corrupted state. // - // The behavior of a process is undefined after it returns normally - // from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or - // SIGSEGV signal that was not generated by kill(), sigqueue(), or - // raise(). + // POSIX says that returning normally from a signal handler for a fault + // is undefined. But in practice, it's better to uninstall the handler + // and return, which will re-run the faulting instruction and cause us + // to die "correctly" (e.g. with a core dump pointing at the faulting + // instruction, not reraise()). if (is_fault(info)) { + if (signal(sig, SIG_DFL) != SIG_ERR) { + return; + } reraise(sig); } |