Skip to content

Commit b824048

Browse files
aclementsianlancetaylor
authored andcommitted
runtime: remove write barrier in WaitForSigusr1
WaitForSigusr1 registers a callback to be called on SIGUSR1 directly from the runtime signal handler. Currently, this callback has a write barrier in it, which can crash with a nil P if the GC is active and the signal arrives on an M that doesn't have a P. Fix this by recording the ID of the M that receives the signal instead of the M itself, since that's all we needed anyway. To make sure there are no other problems, this also lifts the callback into a package function and marks it "go:nowritebarrierrec". Fixes #35248. Updates #35276, since in principle a write barrier at exactly the wrong time while entering the scheduler could cause issues, though I suspect that bug is unrelated. Change-Id: I47b4bc73782efbb613785a93e381d8aaf6850826 Reviewed-on: https://go-review.googlesource.com/c/go/+/204620 Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent f891b7c commit b824048

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

src/runtime/export_unix_test.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type M = m
2222

2323
var waitForSigusr1 struct {
2424
park note
25-
mp *m
25+
mID int64
2626
}
2727

2828
// WaitForSigusr1 blocks until a SIGUSR1 is received. It calls ready
@@ -38,24 +38,34 @@ func WaitForSigusr1(ready func(mp *M), timeoutNS int64) (int64, int64) {
3838
unblocksig(_SIGUSR1)
3939

4040
mp := getg().m
41-
testSigusr1 = func(gp *g) bool {
42-
waitForSigusr1.mp = gp.m
43-
notewakeup(&waitForSigusr1.park)
44-
return true
45-
}
41+
testSigusr1 = waitForSigusr1Callback
4642
ready(mp)
4743
ok := notetsleepg(&waitForSigusr1.park, timeoutNS)
4844
noteclear(&waitForSigusr1.park)
49-
gotM := waitForSigusr1.mp
50-
waitForSigusr1.mp = nil
45+
gotM := waitForSigusr1.mID
5146
testSigusr1 = nil
5247

5348
unlockOSThread()
5449

5550
if !ok {
5651
return -1, -1
5752
}
58-
return mp.id, gotM.id
53+
return mp.id, gotM
54+
}
55+
56+
// waitForSigusr1Callback is called from the signal handler during
57+
// WaitForSigusr1. It must not have write barriers because there may
58+
// not be a P.
59+
//
60+
//go:nowritebarrierrec
61+
func waitForSigusr1Callback(gp *g) bool {
62+
if gp == nil || gp.m == nil {
63+
waitForSigusr1.mID = -1
64+
} else {
65+
waitForSigusr1.mID = gp.m.id
66+
}
67+
notewakeup(&waitForSigusr1.park)
68+
return true
5969
}
6070

6171
// SendSigusr1 sends SIGUSR1 to mp.

0 commit comments

Comments
 (0)