From 801bebefa91205b0b69f2458701aac8169294884 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 21 Jan 2016 21:56:38 -0800 Subject: [PATCH] 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/18835 Reviewed-by: Brad Fitzpatrick Reviewed-by: Mikio Hara Reviewed-by: Russ Cox --- src/runtime/os1_dragonfly.go | 27 +++++++++++---------------- src/runtime/os1_netbsd.go | 27 +++++++++++---------------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/runtime/os1_dragonfly.go b/src/runtime/os1_dragonfly.go index a739ef5a72..bf3e1ccb83 100644 --- a/src/runtime/os1_dragonfly.go +++ b/src/runtime/os1_dragonfly.go @@ -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 diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go index 9ab39ba97d..eab8eb8702 100644 --- a/src/runtime/os1_netbsd.go +++ b/src/runtime/os1_netbsd.go @@ -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 -- 2.50.0