mirror of
https://github.com/golang/go
synced 2024-11-15 00:40:31 -07:00
[release-branch.go1.15] runtime: wait for preemption signals before syscall.Exec
For #41702
For #41704
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 05739d6f17
)
Reviewed-on: https://go-review.googlesource.com/c/go/+/264022
This commit is contained in:
parent
0d489b80dc
commit
3b1f07fff7
@ -1281,6 +1281,14 @@ found:
|
|||||||
checkdead()
|
checkdead()
|
||||||
unlock(&sched.lock)
|
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 {
|
if osStack {
|
||||||
// Return from mstart and let the system thread
|
// Return from mstart and let the system thread
|
||||||
// library free the g0 stack and terminate the thread.
|
// library free the g0 stack and terminate the thread.
|
||||||
@ -3475,11 +3483,24 @@ func syscall_runtime_AfterForkInChild() {
|
|||||||
inForkedChild = false
|
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.
|
// Called from syscall package before Exec.
|
||||||
//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
|
//go:linkname syscall_runtime_BeforeExec syscall.runtime_BeforeExec
|
||||||
func syscall_runtime_BeforeExec() {
|
func syscall_runtime_BeforeExec() {
|
||||||
// Prevent thread creation during exec.
|
// Prevent thread creation during exec.
|
||||||
execLock.lock()
|
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.
|
// Called from syscall package after Exec.
|
||||||
|
@ -336,6 +336,10 @@ func doSigPreempt(gp *g, ctxt *sigctxt) {
|
|||||||
// Acknowledge the preemption.
|
// Acknowledge the preemption.
|
||||||
atomic.Xadd(&gp.m.preemptGen, 1)
|
atomic.Xadd(&gp.m.preemptGen, 1)
|
||||||
atomic.Store(&gp.m.signalPending, 0)
|
atomic.Store(&gp.m.signalPending, 0)
|
||||||
|
|
||||||
|
if GOOS == "darwin" {
|
||||||
|
atomic.Xadd(&pendingPreemptSignals, -1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const preemptMSupported = true
|
const preemptMSupported = true
|
||||||
@ -365,6 +369,10 @@ func preemptM(mp *m) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if atomic.Cas(&mp.signalPending, 0, 1) {
|
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
|
// If multiple threads are preempting the same M, it may send many
|
||||||
// signals to the same M such that it hardly make progress, causing
|
// signals to the same M such that it hardly make progress, causing
|
||||||
// live-lock problem. Apparently this could happen on darwin. See
|
// live-lock problem. Apparently this could happen on darwin. See
|
||||||
@ -436,6 +444,9 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
|||||||
// no non-Go signal handler for sigPreempt.
|
// no non-Go signal handler for sigPreempt.
|
||||||
// The default behavior for sigPreempt is to ignore
|
// The default behavior for sigPreempt is to ignore
|
||||||
// the signal, so badsignal will be a no-op anyway.
|
// the signal, so badsignal will be a no-op anyway.
|
||||||
|
if GOOS == "darwin" {
|
||||||
|
atomic.Xadd(&pendingPreemptSignals, -1)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.fixsigcode(sig)
|
c.fixsigcode(sig)
|
||||||
|
Loading…
Reference in New Issue
Block a user