From 8dc1a158e460d7fdaca3c9317405e7c0dca6e443 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 14 Oct 2019 20:10:48 -0400 Subject: [PATCH] runtime: add test for signalM For #10958, #24543. Change-Id: Ib009a83fe02bc623894f4908fe8f6b266382ba95 Reviewed-on: https://go-review.googlesource.com/c/go/+/201404 Run-TryBot: Austin Clements Reviewed-by: Cherry Zhang --- src/runtime/export_unix_test.go | 39 +++++++++++++++++++++++++++++++++ src/runtime/preemptm_test.go | 35 +++++++++++++++++++++++++++++ src/runtime/signal_unix.go | 11 +++++++--- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 src/runtime/preemptm_test.go diff --git a/src/runtime/export_unix_test.go b/src/runtime/export_unix_test.go index eecdfb7eb2..3f8bff619d 100644 --- a/src/runtime/export_unix_test.go +++ b/src/runtime/export_unix_test.go @@ -17,3 +17,42 @@ func Sigisblocked(i int) bool { sigprocmask(_SIG_SETMASK, nil, &sigmask) return sigismember(&sigmask, i) } + +type M = m + +var waitForSigusr1 struct { + park note + mp *m +} + +// 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. +// +// 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) { + mp := getg().m + testSigusr1 = func(gp *g) bool { + waitForSigusr1.mp = gp.m + notewakeup(&waitForSigusr1.park) + return true + } + ready(mp) + ok := notetsleepg(&waitForSigusr1.park, timeoutNS) + noteclear(&waitForSigusr1.park) + gotM := waitForSigusr1.mp + waitForSigusr1.mp = nil + testSigusr1 = nil + + if !ok { + return -1, -1 + } + return mp.id, gotM.id +} + +// SendSigusr1 sends SIGUSR1 to mp. +func SendSigusr1(mp *M) { + signalM(mp, _SIGUSR1) +} diff --git a/src/runtime/preemptm_test.go b/src/runtime/preemptm_test.go new file mode 100644 index 0000000000..70c6ad55cb --- /dev/null +++ b/src/runtime/preemptm_test.go @@ -0,0 +1,35 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package runtime_test + +import ( + "runtime" + "sync" + "testing" +) + +func TestPreemptM(t *testing.T) { + var want, got int64 + var wg sync.WaitGroup + ready := make(chan *runtime.M) + wg.Add(1) + go func() { + runtime.LockOSThread() + want, got = runtime.WaitForSigusr1(func(mp *runtime.M) { + ready <- mp + }, 1e9) + runtime.UnlockOSThread() + wg.Done() + }() + runtime.SendSigusr1(<-ready) + wg.Wait() + if got == -1 { + t.Fatal("preemptM signal not received") + } else if want != got { + t.Fatalf("signal sent to M %d, but received on M %d", want, got) + } +} diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index cea65282e0..27552c9f33 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -412,10 +412,11 @@ func adjustSignalStack(sig uint32, mp *m, gsigStack *gsignalStack) bool { // GOTRACEBACK=crash when a signal is received. var crashing int32 -// testSigtrap is used by the runtime tests. If non-nil, it is called -// on SIGTRAP. If it returns true, the normal behavior on SIGTRAP is -// suppressed. +// testSigtrap and testSigusr1 are used by the runtime tests. If +// non-nil, it is called on SIGTRAP/SIGUSR1. If it returns true, the +// normal behavior on this signal is suppressed. var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool +var testSigusr1 func(gp *g) bool // sighandler is invoked when a signal occurs. The global g will be // 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) { return } + if sig == _SIGUSR1 && testSigusr1 != nil && testSigusr1(gp) { + return + } + flags := int32(_SigThrow) if sig < uint32(len(sigtable)) { flags = sigtable[sig].flags -- 2.50.0