diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-10-22 02:44:42 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2019-10-22 13:57:02 +0000 |
commit | d29c14f3d2519d72a24c7060d99935f562c37db3 (patch) | |
tree | ab6ab92c6e65cfc0a1e3a92bbf7be5938194d0ab /src/runtime/signal_unix.go | |
parent | 4f364be08de3c5b3d60a134ce9c9d24de834b42d (diff) | |
download | go-d29c14f3d2519d72a24c7060d99935f562c37db3.tar.gz go-d29c14f3d2519d72a24c7060d99935f562c37db3.zip |
runtime: factor signal stack code out of sigtrampgo
This reduces the required nosplit stack size, which permits building
on Solaris with -gcflags=all=-N -l.
Fixes #35046
Change-Id: Icb3a421bb791c73e2f670ecfadbe32daea79789f
Reviewed-on: https://go-review.googlesource.com/c/go/+/202446
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r-- | src/runtime/signal_unix.go | 84 |
1 files changed, 48 insertions, 36 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index 3db6133af0..d5a04b6d48 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -333,43 +333,10 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { } // If some non-Go code called sigaltstack, adjust. - setStack := false var gsignalStack gsignalStack - sp := uintptr(unsafe.Pointer(&sig)) - if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi { - if sp >= g.m.g0.stack.lo && sp < g.m.g0.stack.hi { - // The signal was delivered on the g0 stack. - // This can happen when linked with C code - // using the thread sanitizer, which collects - // signals then delivers them itself by calling - // the signal handler directly when C code, - // including C code called via cgo, calls a - // TSAN-intercepted function such as malloc. - st := stackt{ss_size: g.m.g0.stack.hi - g.m.g0.stack.lo} - setSignalstackSP(&st, g.m.g0.stack.lo) - setGsignalStack(&st, &gsignalStack) - g.m.gsignal.stktopsp = getcallersp() - setStack = true - } else { - var st stackt - sigaltstack(nil, &st) - if st.ss_flags&_SS_DISABLE != 0 { - setg(nil) - needm(0) - noSignalStack(sig) - dropm() - } - stsp := uintptr(unsafe.Pointer(st.ss_sp)) - if sp < stsp || sp >= stsp+st.ss_size { - setg(nil) - needm(0) - sigNotOnStack(sig) - dropm() - } - setGsignalStack(&st, &gsignalStack) - g.m.gsignal.stktopsp = getcallersp() - setStack = true - } + setStack := adjustSignalStack(sig, g.m, &gsignalStack) + if setStack { + g.m.gsignal.stktopsp = getcallersp() } setg(g.m.gsignal) @@ -386,6 +353,51 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { } } +// adjustSignalStack adjusts the current stack guard based on the +// stack pointer that is actually in use while handling a signal. +// We do this in case some non-Go code called sigaltstack. +// This reports whether the stack was adjusted, and if so stores the old +// signal stack in *gsigstack. +//go:nosplit +func adjustSignalStack(sig uint32, mp *m, gsigStack *gsignalStack) bool { + sp := uintptr(unsafe.Pointer(&sig)) + if sp >= mp.gsignal.stack.lo && sp < mp.gsignal.stack.hi { + return false + } + + if sp >= mp.g0.stack.lo && sp < mp.g0.stack.hi { + // The signal was delivered on the g0 stack. + // This can happen when linked with C code + // using the thread sanitizer, which collects + // signals then delivers them itself by calling + // the signal handler directly when C code, + // including C code called via cgo, calls a + // TSAN-intercepted function such as malloc. + st := stackt{ss_size: mp.g0.stack.hi - mp.g0.stack.lo} + setSignalstackSP(&st, mp.g0.stack.lo) + setGsignalStack(&st, gsigStack) + return true + } + + var st stackt + sigaltstack(nil, &st) + if st.ss_flags&_SS_DISABLE != 0 { + setg(nil) + needm(0) + noSignalStack(sig) + dropm() + } + stsp := uintptr(unsafe.Pointer(st.ss_sp)) + if sp < stsp || sp >= stsp+st.ss_size { + setg(nil) + needm(0) + sigNotOnStack(sig) + dropm() + } + setGsignalStack(&st, gsigStack) + return true +} + // crashing is the number of m's we have waited for when implementing // GOTRACEBACK=crash when a signal is received. var crashing int32 |