Commit 801bebef authored by Ian Lance Taylor's avatar Ian Lance Taylor

runtime: always install new signal stack on NetBSD and DragonFly

On NetBSD and DragonFly a newly created thread inherits the signal stack
of the creating thread.  That means that in a cgo program a C thread
created using pthread_create will get the signal stack of the creating
thread, most likely a Go thread.  This will then lead to chaos if two
signals occur simultaneously.

We can't fix the general case.  But we can fix the case of a C thread
that calls a Go function, by installing a new signal stack and then
dropping it when we return to C.  That will break the case of a C thread
that calls sigaltstack and then calls Go, because we will drop the C
thread's alternate signal stack as we return from Go.  Still, this is
the 1.5 behavior.  And what else can we do?

Fixes #14051.
Fixes #14052.
Fixes #14067.

Change-Id: Iee286ca50b50ec712a4d929c7121c35e2383a7b9
Reviewed-on: https://go-review.googlesource.com/18835Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarMikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 3415d0c4
......@@ -140,22 +140,17 @@ func minit() {
// m.procid is a uint64, but lwp_start writes an int32. Fix it up.
_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
// Initialize signal handling
var st sigaltstackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
} else {
// Use existing signal stack.
stsp := uintptr(unsafe.Pointer(st.ss_sp))
_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.newSigstack = false
}
// Initialize signal handling.
// On DragonFly a thread created by pthread_create inherits
// the signal stack of the creating thread. We always create
// a new signal stack here, to avoid having two Go threads
// using the same signal stack. This breaks the case of a
// thread created in C that calls sigaltstack and then calls a
// Go function, because we will lose track of the C code's
// sigaltstack, but it's the best we can do.
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
......
......@@ -172,22 +172,17 @@ func minit() {
_g_ := getg()
_g_.m.procid = uint64(lwp_self())
// Initialize signal handling
var st sigaltstackt
sigaltstack(nil, &st)
if st.ss_flags&_SS_DISABLE != 0 {
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
} else {
// Use existing signal stack.
stsp := uintptr(unsafe.Pointer(st.ss_sp))
_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.newSigstack = false
}
// Initialize signal handling.
// On NetBSD a thread created by pthread_create inherits the
// signal stack of the creating thread. We always create a
// new signal stack here, to avoid having two Go threads using
// the same signal stack. This breaks the case of a thread
// created in C that calls sigaltstack and then calls a Go
// function, because we will lose track of the C code's
// sigaltstack, but it's the best we can do.
signalstack(&_g_.m.gsignal.stack)
_g_.m.newSigstack = true
// restore signal mask from m.sigmask and unblock essential signals
nmask := _g_.m.sigmask
......
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