diff options
author | Elias Naur <elias.naur@gmail.com> | 2017-08-19 16:59:19 +0200 |
---|---|---|
committer | Elias Naur <elias.naur@gmail.com> | 2017-08-29 07:40:19 +0000 |
commit | c3189cee717a47dd7936d9f82904db72b28293f6 (patch) | |
tree | e3fc16aff861b031fec26f74f79ed10ce085ff5a /src/runtime/signal_unix.go | |
parent | 176cd48e574817bbb912c139396324c187b31279 (diff) | |
download | go-c3189cee717a47dd7936d9f82904db72b28293f6.tar.gz go-c3189cee717a47dd7936d9f82904db72b28293f6.zip |
runtime: forward crashing signals to late handlers
CL 49590 made it possible for external signal handlers to catch
signals from a crashing Go process. This CL extends that support
to handlers registered after the Go runtime has initialized.
Updates #20392 (and possibly fix it).
Change-Id: I18eccd5e958a505f4d1782a7fc51c16bd3a4ff9c
Reviewed-on: https://go-review.googlesource.com/57291
Run-TryBot: Elias Naur <elias.naur@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r-- | src/runtime/signal_unix.go | 37 |
1 files changed, 13 insertions, 24 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 973e5f924f..5ea4b9f631 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -405,13 +405,8 @@ func sigpanic() { //go:nowritebarrierrec func dieFromSignal(sig uint32) { unblocksig(sig) - // First, try any signal handler installed before the runtime - // initialized. - fn := atomic.Loaduintptr(&fwdSig[sig]) - // On Darwin, sigtramp is called even for non-Go signal handlers. // Mark the signal as unhandled to ensure it is forwarded. atomic.Store(&handlingSig[sig], 0) - setsig(sig, fn) raise(sig) // That should have killed us. On some systems, though, raise @@ -601,17 +596,23 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { return false } fwdFn := atomic.Loaduintptr(&fwdSig[sig]) + flags := sigtable[sig].flags - if !signalsOK { - // The only way we can get here is if we are in a - // library or archive, we installed a signal handler - // at program startup, but the Go runtime has not yet - // been initialized. + // If we aren't handling the signal, forward it. + if atomic.Load(&handlingSig[sig]) == 0 || !signalsOK { + // If the signal is ignored, doing nothing is the same as forwarding. + if fwdFn == _SIG_IGN || (fwdFn == _SIG_DFL && flags&_SigIgn != 0) { + return true + } + // We are not handling the signal and there is no other handler to forward to. + // Crash with the default behavior. if fwdFn == _SIG_DFL { + setsig(sig, _SIG_DFL) dieFromSignal(sig) - } else { - sigfwd(fwdFn, sig, info, ctx) + return false } + + sigfwd(fwdFn, sig, info, ctx) return true } @@ -620,18 +621,6 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { return false } - // If we aren't handling the signal, forward it. - // Really if we aren't handling the signal, we shouldn't get here, - // but on Darwin setsigstack can lead us here because it sets - // the sa_tramp field. The sa_tramp field is not returned by - // sigaction, so the fix for that is non-obvious. - if atomic.Load(&handlingSig[sig]) == 0 { - sigfwd(fwdFn, sig, info, ctx) - return true - } - - flags := sigtable[sig].flags - c := &sigctxt{info, ctx} // Only forward synchronous signals and SIGPIPE. // Unfortunately, user generated SIGPIPEs will also be forwarded, because si_code |