aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/signal_unix.go
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-03-16 20:08:00 -0400
committerCherry Zhang <cherryyz@google.com>2020-03-18 16:00:44 +0000
commit0c0e8f224d5724e317952f77d215a752a3a7b7d9 (patch)
treec190a79fde5ddd44ab0987067accfc3ae84b597e /src/runtime/signal_unix.go
parent6412750f32224f6820f781d09b2092c5c358dddc (diff)
downloadgo-0c0e8f224d5724e317952f77d215a752a3a7b7d9.tar.gz
go-0c0e8f224d5724e317952f77d215a752a3a7b7d9.zip
runtime: don't send preemption signal if there is a signal pending
If multiple threads call preemptone to preempt the same M, it may send many signals to the same M such that it hardly make progress, causing live-lock problem. Only send a signal if there isn't already one pending. Fixes #37741. Change-Id: Id94adb0b95acbd18b23abe637a8dcd81ab41b452 Reviewed-on: https://go-review.googlesource.com/c/go/+/223737 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r--src/runtime/signal_unix.go10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 32b192c977..b8f27d1147 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -333,6 +333,7 @@ func doSigPreempt(gp *g, ctxt *sigctxt) {
// Acknowledge the preemption.
atomic.Xadd(&gp.m.preemptGen, 1)
+ atomic.Store(&gp.m.signalPending, 0)
}
const preemptMSupported = pushCallSupported
@@ -359,7 +360,14 @@ func preemptM(mp *m) {
// required).
return
}
- signalM(mp, sigPreempt)
+ if atomic.Cas(&mp.signalPending, 0, 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
+ // issue #37741.
+ // Only send a signal if there isn't already one pending.
+ signalM(mp, sigPreempt)
+ }
}
// sigFetchG fetches the value of G safely when running in a signal handler.