Commit c3189cee authored by Elias Naur's avatar Elias Naur

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: default avatarIan Lance Taylor <iant@golang.org>
parent 176cd48e
......@@ -430,12 +430,16 @@ func TestCatchPanic(t *testing.T) {
t.Fatal(err)
}
cmd := testEnv(exec.Command(exe, "CgoCatchPanic"))
// Make sure a panic results in a crash.
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
// Tell testprogcgo to install an early signal handler for SIGABRT
cmd.Env = append(cmd.Env, "CGOCATCHPANIC_INSTALL_HANDLER=1")
if out, err := cmd.CombinedOutput(); err != nil {
t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
for _, early := range []bool{true, false} {
cmd := testEnv(exec.Command(exe, "CgoCatchPanic"))
// Make sure a panic results in a crash.
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
if early {
// Tell testprogcgo to install an early signal handler for SIGABRT
cmd.Env = append(cmd.Env, "CGOCATCHPANIC_EARLY_HANDLER=1")
}
if out, err := cmd.CombinedOutput(); err != nil {
t.Errorf("testprogcgo CgoCatchPanic failed: %v\n%s", err, out)
}
}
}
......@@ -604,6 +604,7 @@ const (
_SigGoExit // cause all runtime procs to exit (only used on Plan 9).
_SigSetStack // add SA_ONSTACK to libc handler
_SigUnblock // unblocked in minit
_SigIgn // _SIG_DFL action is to ignore the signal
)
// Layout of in-memory per-function information prepared by linker
......
......@@ -21,20 +21,20 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify + _SigIgn, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
/* 28 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify + _SigIgn, "SIGINFO: status request from keyboard"},
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
}
......@@ -21,20 +21,20 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify + _SigIgn, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
/* 28 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify + _SigIgn, "SIGINFO: status request from keyboard"},
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 32 */ {_SigNotify, "SIGTHR: reserved"},
......
......@@ -21,20 +21,20 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify + _SigIgn, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
/* 28 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify + _SigIgn, "SIGINFO: status request from keyboard"},
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 32 */ {_SigNotify, "SIGTHR: reserved"},
......
......@@ -26,13 +26,13 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
......
......@@ -21,20 +21,20 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify + _SigIgn, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
/* 28 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify + _SigIgn, "SIGINFO: status request from keyboard"},
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 32 */ {_SigNotify, "SIGTHR: reserved"},
......
......@@ -21,13 +21,13 @@ var sigtable = [...]sigTabT{
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 16 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 17 */ {0, "SIGSTOP: stop"},
/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 19 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue after stop"},
/* 20 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
......
......@@ -23,16 +23,16 @@ var sigtable = [...]sigTabT{
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: software termination signal from kill"},
/* 16 */ {_SigNotify, "SIGUSR1: user defined signal 1"},
/* 17 */ {_SigNotify, "SIGUSR2: user defined signal 2"},
/* 18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status change alias (POSIX)"},
/* 18 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status change alias (POSIX)"},
/* 19 */ {_SigNotify, "SIGPWR: power-fail restart"},
/* 20 */ {_SigNotify, "SIGWINCH: window size change"},
/* 21 */ {_SigNotify, "SIGURG: urgent socket condition"},
/* 20 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 21 */ {_SigNotify + _SigIgn, "SIGURG: urgent socket condition"},
/* 22 */ {_SigNotify, "SIGPOLL: pollable event occurred"},
/* 23 */ {0, "SIGSTOP: stop (cannot be caught or ignored)"},
/* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: user stop requested from tty"},
/* 25 */ {_SigNotify + _SigDefault, "SIGCONT: stopped process has been continued"},
/* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background tty read attempted"},
/* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background tty write attempted"},
/* 24 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: user stop requested from tty"},
/* 25 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: stopped process has been continued"},
/* 26 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background tty read attempted"},
/* 27 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background tty write attempted"},
/* 28 */ {_SigNotify, "SIGVTALRM: virtual timer expired"},
/* 29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling timer expired"},
/* 30 */ {_SigNotify, "SIGXCPU: exceeded cpu limit"},
......
......@@ -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
......
......@@ -28,18 +28,18 @@ var sigtable = [...]sigTabT{
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigThrow + _SigUnblock, "SIGSTKFLT: stack fault"},
/* 17 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 18 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
/* 17 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 18 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue"},
/* 19 */ {0, "SIGSTOP: stop, unblockable"},
/* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 20 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 21 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 22 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 23 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
/* 28 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
/* 31 */ {_SigThrow, "SIGSYS: bad system call"},
......
......@@ -26,16 +26,16 @@ var sigtable = [...]sigTabT{
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
/* 16 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
/* 17 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
/* 18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
/* 18 */ {_SigNotify + _SigUnblock + _SigIgn, "SIGCHLD: child status has changed"},
/* 19 */ {_SigNotify, "SIGPWR: power failure restart"},
/* 20 */ {_SigNotify, "SIGWINCH: window size change"},
/* 21 */ {_SigNotify, "SIGURG: urgent condition on socket"},
/* 20 */ {_SigNotify + _SigIgn, "SIGWINCH: window size change"},
/* 21 */ {_SigNotify + _SigIgn, "SIGURG: urgent condition on socket"},
/* 22 */ {_SigNotify, "SIGIO: i/o now possible"},
/* 23 */ {0, "SIGSTOP: stop, unblockable"},
/* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
/* 25 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
/* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
/* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
/* 24 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTSTP: keyboard stop"},
/* 25 */ {_SigNotify + _SigDefault + _SigIgn, "SIGCONT: continue"},
/* 26 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTIN: background read from tty"},
/* 27 */ {_SigNotify + _SigDefault + _SigIgn, "SIGTTOU: background write to tty"},
/* 28 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
/* 29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
/* 30 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
......
......@@ -17,17 +17,21 @@ static void abrthandler(int signum) {
}
}
static void __attribute__ ((constructor)) sigsetup(void) {
void registerAbortHandler() {
struct sigaction act;
if (getenv("CGOCATCHPANIC_INSTALL_HANDLER") == NULL)
return;
memset(&act, 0, sizeof act);
act.sa_handler = abrthandler;
sigaction(SIGABRT, &act, NULL);
}
static void __attribute__ ((constructor)) sigsetup(void) {
if (getenv("CGOCATCHPANIC_EARLY_HANDLER") == NULL)
return;
registerAbortHandler();
}
*/
import "C"
import "os"
func init() {
register("CgoCatchPanic", CgoCatchPanic)
......@@ -35,5 +39,8 @@ func init() {
// Test that the SIGABRT raised by panic can be caught by an early signal handler.
func CgoCatchPanic() {
if _, ok := os.LookupEnv("CGOCATCHPANIC_EARLY_HANDLER"); !ok {
C.registerAbortHandler()
}
panic("catch me")
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment