Commit d29c14f3 authored by Ian Lance Taylor's avatar Ian Lance Taylor

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/+/202446Reviewed-by: default avatarBryan C. Mills <bcmills@google.com>
parent 4f364be0
...@@ -333,43 +333,10 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { ...@@ -333,43 +333,10 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
} }
// If some non-Go code called sigaltstack, adjust. // If some non-Go code called sigaltstack, adjust.
setStack := false
var gsignalStack gsignalStack var gsignalStack gsignalStack
sp := uintptr(unsafe.Pointer(&sig)) setStack := adjustSignalStack(sig, g.m, &gsignalStack)
if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi { if setStack {
if sp >= g.m.g0.stack.lo && sp < g.m.g0.stack.hi { g.m.gsignal.stktopsp = getcallersp()
// 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
}
} }
setg(g.m.gsignal) setg(g.m.gsignal)
...@@ -386,6 +353,51 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { ...@@ -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 // crashing is the number of m's we have waited for when implementing
// GOTRACEBACK=crash when a signal is received. // GOTRACEBACK=crash when a signal is received.
var crashing int32 var crashing int32
......
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