diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-11-07 21:08:48 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2019-11-12 05:35:33 +0000 |
commit | 99957b6930c76b683dbca1ff4bcdd56e59b1e035 (patch) | |
tree | 48e93149df7e0b683450a9be932a58a1c56da8ab /src/runtime/export_unix_test.go | |
parent | d22b5735e74c1e5905d1574853cb9a9f48da1afe (diff) | |
download | go-99957b6930c76b683dbca1ff4bcdd56e59b1e035.tar.gz go-99957b6930c76b683dbca1ff4bcdd56e59b1e035.zip |
runtime: use pipe rather than note in TestSignalM
At least on Darwin notewakeup is not async-signal-safe.
Fixes #35276
Change-Id: I1d7523715e8e77dbd7f21d9b1ed131e52d46cc41
Reviewed-on: https://go-review.googlesource.com/c/go/+/206078
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/export_unix_test.go')
-rw-r--r-- | src/runtime/export_unix_test.go | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/src/runtime/export_unix_test.go b/src/runtime/export_unix_test.go index 375513337e..621488eaba 100644 --- a/src/runtime/export_unix_test.go +++ b/src/runtime/export_unix_test.go @@ -6,6 +6,8 @@ package runtime +import "unsafe" + var NonblockingPipe = nonblockingPipe var Pipe = pipe var SetNonblock = setNonblock @@ -26,33 +28,45 @@ func Sigisblocked(i int) bool { type M = m var waitForSigusr1 struct { - park note - mID int64 + rdpipe int32 + wrpipe int32 + mID int64 } // WaitForSigusr1 blocks until a SIGUSR1 is received. It calls ready // when it is set up to receive SIGUSR1. The ready function should -// cause a SIGUSR1 to be sent. +// cause a SIGUSR1 to be sent. The r and w arguments are a pipe that +// the signal handler can use to report when the signal is received. // // Once SIGUSR1 is received, it returns the ID of the current M and -// the ID of the M the SIGUSR1 was received on. If no SIGUSR1 is -// received for timeoutNS nanoseconds, it returns -1. -func WaitForSigusr1(ready func(mp *M), timeoutNS int64) (int64, int64) { +// the ID of the M the SIGUSR1 was received on. If the caller writes +// a non-zero byte to w, WaitForSigusr1 returns immediately with -1, -1. +func WaitForSigusr1(r, w int32, ready func(mp *M)) (int64, int64) { lockOSThread() // Make sure we can receive SIGUSR1. unblocksig(_SIGUSR1) + waitForSigusr1.rdpipe = r + waitForSigusr1.wrpipe = w + mp := getg().m testSigusr1 = waitForSigusr1Callback ready(mp) - ok := notetsleepg(&waitForSigusr1.park, timeoutNS) - noteclear(&waitForSigusr1.park) + + // Wait for the signal. We use a pipe rather than a note + // because write is always async-signal-safe. + entersyscallblock() + var b byte + read(waitForSigusr1.rdpipe, noescape(unsafe.Pointer(&b)), 1) + exitsyscall() + gotM := waitForSigusr1.mID testSigusr1 = nil unlockOSThread() - if !ok { + if b != 0 { + // timeout signal from caller return -1, -1 } return mp.id, gotM @@ -69,7 +83,8 @@ func waitForSigusr1Callback(gp *g) bool { } else { waitForSigusr1.mID = gp.m.id } - notewakeup(&waitForSigusr1.park) + b := byte(0) + write(uintptr(waitForSigusr1.wrpipe), noescape(unsafe.Pointer(&b)), 1) return true } |