Skip to content

Commit

Permalink
[release-branch.go1.14] runtime: wait for preemption signals before s…
Browse files Browse the repository at this point in the history
…yscall.Exec

For #41702
For #41703
For #42023

Change-Id: If07f40b1d73b8f276ee28ffb8b7214175e56c24d
Reviewed-on: https://go-review.googlesource.com/c/go/+/262817
Trust: Ian Lance Taylor <[email protected]>
Trust: Bryan C. Mills <[email protected]>
Run-TryBot: Ian Lance Taylor <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Cherry Zhang <[email protected]>
(cherry picked from commit 05739d6)
Reviewed-on: https://go-review.googlesource.com/c/go/+/264023
  • Loading branch information
ianlancetaylor committed Oct 20, 2020
1 parent b581ccd commit 768b647
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/runtime/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions src/runtime/signal_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 768b647

Please sign in to comment.