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)
+ }
}
}
_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
/* 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"},
}
/* 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"},
/* 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"},
/* 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"},
/* 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"},
/* 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"},
/* 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"},
//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
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
}
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
/* 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"},
/* 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"},
}
}
-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)
// 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")
}