runtime: fix bad signal stack when using cgo-created threads and async signals
Cgo-created threads transition between having associated Go g's and m's and not.
A signal arriving during the transition could think it was safe and appropriate to
run Go signal handlers when it was in fact not.
Avoid the race by masking all signals during the transition.
Fixes #12277.
Change-Id: Ie9711bc1d098391d58362492197a7e0f5b497d14
Reviewed-on: https://go-review.googlesource.com/16915
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
index 11034a6..0cfb134 100644
--- a/src/runtime/os1_openbsd.go
+++ b/src/runtime/os1_openbsd.go
@@ -148,6 +148,7 @@
mp.gsignal.m = mp
}
+//go:nosplit
func msigsave(mp *m) {
smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
@@ -156,6 +157,17 @@
*smask = sigprocmask(_SIG_BLOCK, 0)
}
+//go:nosplit
+func msigrestore(mp *m) {
+ smask := *(*uint32)(unsafe.Pointer(&mp.sigmask))
+ sigprocmask(_SIG_SETMASK, smask)
+}
+
+//go:nosplit
+func sigblock() {
+ sigprocmask(_SIG_SETMASK, sigset_all)
+}
+
// Called to initialize a new m (including the bootstrap m).
// Called on the new thread, can not allocate memory.
func minit() {
@@ -178,10 +190,8 @@
}
// Called from dropm to undo the effect of an minit.
+//go:nosplit
func unminit() {
- _g_ := getg()
- smask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
- sigprocmask(_SIG_SETMASK, smask)
signalstack(nil)
}
@@ -224,6 +234,7 @@
return sa.sa_sigaction
}
+//go:nosplit
func signalstack(s *stack) {
var st stackt
if s == nil {