Skip to content

Commit 8dc1a15

Browse files
committed
runtime: add test for signalM
For golang#10958, golang#24543. Change-Id: Ib009a83fe02bc623894f4908fe8f6b266382ba95 Reviewed-on: https://go-review.googlesource.com/c/go/+/201404 Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
1 parent 42aab4b commit 8dc1a15

File tree

3 files changed

+82
-3
lines changed

3 files changed

+82
-3
lines changed

src/runtime/export_unix_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,42 @@ func Sigisblocked(i int) bool {
1717
sigprocmask(_SIG_SETMASK, nil, &sigmask)
1818
return sigismember(&sigmask, i)
1919
}
20+
21+
type M = m
22+
23+
var waitForSigusr1 struct {
24+
park note
25+
mp *m
26+
}
27+
28+
// WaitForSigusr1 blocks until a SIGUSR1 is received. It calls ready
29+
// when it is set up to receive SIGUSR1. The ready function should
30+
// cause a SIGUSR1 to be sent.
31+
//
32+
// Once SIGUSR1 is received, it returns the ID of the current M and
33+
// the ID of the M the SIGUSR1 was received on. If no SIGUSR1 is
34+
// received for timeoutNS nanoseconds, it returns -1.
35+
func WaitForSigusr1(ready func(mp *M), timeoutNS int64) (int64, int64) {
36+
mp := getg().m
37+
testSigusr1 = func(gp *g) bool {
38+
waitForSigusr1.mp = gp.m
39+
notewakeup(&waitForSigusr1.park)
40+
return true
41+
}
42+
ready(mp)
43+
ok := notetsleepg(&waitForSigusr1.park, timeoutNS)
44+
noteclear(&waitForSigusr1.park)
45+
gotM := waitForSigusr1.mp
46+
waitForSigusr1.mp = nil
47+
testSigusr1 = nil
48+
49+
if !ok {
50+
return -1, -1
51+
}
52+
return mp.id, gotM.id
53+
}
54+
55+
// SendSigusr1 sends SIGUSR1 to mp.
56+
func SendSigusr1(mp *M) {
57+
signalM(mp, _SIGUSR1)
58+
}

src/runtime/preemptm_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
6+
7+
package runtime_test
8+
9+
import (
10+
"runtime"
11+
"sync"
12+
"testing"
13+
)
14+
15+
func TestPreemptM(t *testing.T) {
16+
var want, got int64
17+
var wg sync.WaitGroup
18+
ready := make(chan *runtime.M)
19+
wg.Add(1)
20+
go func() {
21+
runtime.LockOSThread()
22+
want, got = runtime.WaitForSigusr1(func(mp *runtime.M) {
23+
ready <- mp
24+
}, 1e9)
25+
runtime.UnlockOSThread()
26+
wg.Done()
27+
}()
28+
runtime.SendSigusr1(<-ready)
29+
wg.Wait()
30+
if got == -1 {
31+
t.Fatal("preemptM signal not received")
32+
} else if want != got {
33+
t.Fatalf("signal sent to M %d, but received on M %d", want, got)
34+
}
35+
}

src/runtime/signal_unix.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,11 @@ func adjustSignalStack(sig uint32, mp *m, gsigStack *gsignalStack) bool {
412412
// GOTRACEBACK=crash when a signal is received.
413413
var crashing int32
414414

415-
// testSigtrap is used by the runtime tests. If non-nil, it is called
416-
// on SIGTRAP. If it returns true, the normal behavior on SIGTRAP is
417-
// suppressed.
415+
// testSigtrap and testSigusr1 are used by the runtime tests. If
416+
// non-nil, it is called on SIGTRAP/SIGUSR1. If it returns true, the
417+
// normal behavior on this signal is suppressed.
418418
var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
419+
var testSigusr1 func(gp *g) bool
419420

420421
// sighandler is invoked when a signal occurs. The global g will be
421422
// set to a gsignal goroutine and we will be running on the alternate
@@ -441,6 +442,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
441442
return
442443
}
443444

445+
if sig == _SIGUSR1 && testSigusr1 != nil && testSigusr1(gp) {
446+
return
447+
}
448+
444449
flags := int32(_SigThrow)
445450
if sig < uint32(len(sigtable)) {
446451
flags = sigtable[sig].flags

0 commit comments

Comments
 (0)