aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-10-15 14:39:12 -0700
committerIan Lance Taylor <iant@golang.org>2020-10-20 23:46:37 +0000
commit768b64711ae4292bd9a02c9cc8d44282f5fac66b (patch)
tree0febc157dc3ccac2a14322a878438c4b52cc45cb
parentb581ccd46ef243c6a64c343e79b039022da8a7a2 (diff)
downloadgo-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.go21
-rw-r--r--src/runtime/signal_unix.go11
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)