summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sighook.c16
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);
}