diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index a9a65d5164..3db6133af0 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -242,10 +242,26 @@ func setProcessCPUProfiler(hz int32) { } } else { // If the Go signal handler should be disabled by default, - // disable it if it is enabled. + // switch back to the signal handler that was installed + // when we enabled profiling. We don't try to handle the case + // of a program that changes the SIGPROF handler while Go + // profiling is enabled. + // + // If no signal handler was installed before, then start + // ignoring SIGPROF signals. We do this, rather than change + // to SIG_DFL, because there may be a pending SIGPROF + // signal that has not yet been delivered to some other thread. + // If we change to SIG_DFL here, the program will crash + // when that SIGPROF is delivered. We assume that programs + // that use profiling don't want to crash on a stray SIGPROF. + // See issue 19320. if !sigInstallGoHandler(_SIGPROF) { if atomic.Cas(&handlingSig[_SIGPROF], 1, 0) { - setsig(_SIGPROF, atomic.Loaduintptr(&fwdSig[_SIGPROF])) + h := atomic.Loaduintptr(&fwdSig[_SIGPROF]) + if h == _SIG_DFL { + h = _SIG_IGN + } + setsig(_SIGPROF, h) } } }