Skip to content

Commit

Permalink
sighook: Return instead of re-raising for faults
Browse files Browse the repository at this point in the history
This makes the death look exactly like it would if we didn't handle the
signal at all.  Coredumps will point at the right instruction, segfaults
will get logged in dmesg again, etc.

Technically POSIX says this is undefined, but if we get a fault, we've
already done something undefined anyway ;)

Link: rust-lang/rust#26458
  • Loading branch information
tavianator committed Nov 23, 2024
1 parent f7b813f commit aecdabb
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/sighook.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit aecdabb

Please sign in to comment.