]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: always install new signal stack on NetBSD and DragonFly
authorIan Lance Taylor <iant@golang.org>
Fri, 22 Jan 2016 05:56:38 +0000 (21:56 -0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 25 Jan 2016 02:50:40 +0000 (02:50 +0000)
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 <bradfitz@golang.org>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
src/runtime/os1_dragonfly.go
src/runtime/os1_netbsd.go

index a739ef5a72410d91c370723e302aa444482e2ae9..bf3e1ccb839b23383a6b745a1ad563a4ce08b667 100644 (file)
@@ -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
index 9ab39ba97d954e00970fed3f17d64676bb6b1b9f..eab8eb87024e6a47911043981e0c45c148260faa 100644 (file)
@@ -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