mirror of
https://github.com/golang/go
synced 2024-10-02 20:41:21 -06:00
df2b2eb63d
The current runtime attempts to forward signals generated by non-Go code to the original signal handler. If it can't call the original handler directly, it currently attempts to re-raise the signal after resetting the handler. In this case, the original context is lost. This fix prevents that problem by simply returning from the go signal handler after resetting the original handler. It only does this when the original handler is the system default handler, which in all cases is known to not recover. The signal is not reset, so it is retriggered and the original handler takes over with the proper context. Fixes #14899 Change-Id: Ib1c19dfa4b50d9732d7a453de3784c8141e1cbb3 Reviewed-on: https://go-review.googlesource.com/21006 Reviewed-by: Ian Lance Taylor <iant@golang.org>
88 lines
3.2 KiB
Go
88 lines
3.2 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package runtime
|
|
|
|
import "unsafe"
|
|
|
|
type sigTabT struct {
|
|
flags int32
|
|
name string
|
|
}
|
|
|
|
var sigtable = [...]sigTabT{
|
|
/* 0 */ {0, "SIGNONE: no trap"},
|
|
/* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
|
|
/* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
|
|
/* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
|
|
/* 4 */ {_SigThrow, "SIGILL: illegal instruction"},
|
|
/* 5 */ {_SigThrow, "SIGTRAP: trace trap"},
|
|
/* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
|
|
/* 7 */ {_SigThrow, "SIGEMT: emulate instruction executed"},
|
|
/* 8 */ {_SigPanic, "SIGFPE: floating-point exception"},
|
|
/* 9 */ {0, "SIGKILL: kill"},
|
|
/* 10 */ {_SigPanic, "SIGBUS: bus error"},
|
|
/* 11 */ {_SigPanic, "SIGSEGV: segmentation violation"},
|
|
/* 12 */ {_SigThrow, "SIGSYS: bad system call"},
|
|
/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
|
|
/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
|
|
/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
|
|
/* 16 */ {_SigNotify, "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"},
|
|
/* 23 */ {_SigNotify, "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, "SIGPROF: profiling alarm clock"},
|
|
/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
|
|
/* 29 */ {_SigNotify, "SIGINFO: status request from keyboard"},
|
|
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
|
|
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
|
|
/* 32 */ {_SigNotify, "SIGTHR: reserved"},
|
|
}
|
|
|
|
//go:nosplit
|
|
//go:nowritebarrierrec
|
|
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
|
if sigfwdgo(sig, info, ctx) {
|
|
return
|
|
}
|
|
g := getg()
|
|
if g == nil {
|
|
badsignal(uintptr(sig), &sigctxt{info, ctx})
|
|
return
|
|
}
|
|
|
|
// If some non-Go code called sigaltstack, adjust.
|
|
sp := uintptr(unsafe.Pointer(&sig))
|
|
if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
|
|
var st stackt
|
|
sigaltstack(nil, &st)
|
|
if st.ss_flags&_SS_DISABLE != 0 {
|
|
setg(nil)
|
|
cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
|
|
}
|
|
stsp := uintptr(unsafe.Pointer(st.ss_sp))
|
|
if sp < stsp || sp >= stsp+st.ss_size {
|
|
setg(nil)
|
|
cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
|
|
}
|
|
g.m.gsignal.stack.lo = stsp
|
|
g.m.gsignal.stack.hi = stsp + st.ss_size
|
|
g.m.gsignal.stackguard0 = stsp + _StackGuard
|
|
g.m.gsignal.stackguard1 = stsp + _StackGuard
|
|
g.m.gsignal.stackAlloc = st.ss_size
|
|
g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
|
|
}
|
|
|
|
setg(g.m.gsignal)
|
|
sighandler(sig, info, ctx, g)
|
|
setg(g)
|
|
}
|