diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-10-15 14:39:12 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-10-20 23:46:37 +0000 |
commit | 768b64711ae4292bd9a02c9cc8d44282f5fac66b (patch) | |
tree | 0febc157dc3ccac2a14322a878438c4b52cc45cb | |
parent | b581ccd46ef243c6a64c343e79b039022da8a7a2 (diff) | |
download | go-768b64711ae4292bd9a02c9cc8d44282f5fac66b.tar.gz go-768b64711ae4292bd9a02c9cc8d44282f5fac66b.zip |
[release-branch.go1.14] runtime: wait for preemption signals before syscall.Exec
For #41702
For #41703
For #42023
Change-Id: If07f40b1d73b8f276ee28ffb8b7214175e56c24d
Reviewed-on: https://go-review.googlesource.com/c/go/+/262817
Trust: Ian Lance Taylor <iant@golang.org>
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
(cherry picked from commit 05739d6f17c57f09264272621b88725a463234d0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/264023
-rw-r--r-- | src/runtime/proc.go | 21 | ||||
-rw-r--r-- | src/runtime/signal_unix.go | 11 |
2 files changed, 32 insertions, 0 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 378d02dea7..76a71be123 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1221,6 +1221,14 @@ found: checkdead() unlock(&sched.lock) + if GOOS == "darwin" { + // Make sure pendingPreemptSignals is correct when an M exits. + // For #41702. + if atomic.Load(&m.signalPending) != 0 { + atomic.Xadd(&pendingPreemptSignals, -1) + } + } + if osStack { // Return from mstart and let the system thread // library free the g0 stack and terminate the thread. @@ -3375,11 +3383,24 @@ func syscall_runtime_AfterForkInChild() { inForkedChild = false } +// pendingPreemptSignals is the number of preemption signals +// that have been sent but not received. This is only used on Darwin. +// For #41702. +var pendingPreemptSignals uint32 + // Called from syscall package before Exec. //go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec func syscall_runtime_BeforeExec() { // Prevent thread creation during exec. execLock.lock() + + // On Darwin, wait for all pending preemption signals to + // be received. See issue #41702. + if GOOS == "darwin" { + for int32(atomic.Load(&pendingPreemptSignals)) > 0 { + osyield() + } + } } // Called from syscall package after Exec. diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go index c7a6c2197c..9f081d41c5 100644 --- a/src/runtime/signal_unix.go +++ b/src/runtime/signal_unix.go @@ -334,6 +334,10 @@ func doSigPreempt(gp *g, ctxt *sigctxt) { // Acknowledge the preemption. atomic.Xadd(&gp.m.preemptGen, 1) atomic.Store(&gp.m.signalPending, 0) + + if GOOS == "darwin" { + atomic.Xadd(&pendingPreemptSignals, -1) + } } const preemptMSupported = pushCallSupported @@ -368,6 +372,10 @@ func preemptM(mp *m) { } if atomic.Cas(&mp.signalPending, 0, 1) { + if GOOS == "darwin" { + atomic.Xadd(&pendingPreemptSignals, 1) + } + // If multiple threads are preempting the same M, it may send many // signals to the same M such that it hardly make progress, causing // live-lock problem. Apparently this could happen on darwin. See @@ -439,6 +447,9 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { // no non-Go signal handler for sigPreempt. // The default behavior for sigPreempt is to ignore // the signal, so badsignal will be a no-op anyway. + if GOOS == "darwin" { + atomic.Xadd(&pendingPreemptSignals, -1) + } return } c.fixsigcode(sig) |