aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/signal_unix.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-11-22 19:12:12 -0800
committerIan Lance Taylor <iant@golang.org>2017-11-30 23:29:30 +0000
commiteb97160f46cb18770ccb0bd57a08457c9ff20ccc (patch)
tree2f7760872111605d145d8c0d67b3a54fe019aa54 /src/runtime/signal_unix.go
parentb23096b514e6290b1ff31183516378fe91e16251 (diff)
downloadgo-eb97160f46cb18770ccb0bd57a08457c9ff20ccc.tar.gz
go-eb97160f46cb18770ccb0bd57a08457c9ff20ccc.zip
runtime: don't block signals that will kill the program
Otherwise we may delay the delivery of these signals for an arbitrary length of time. We are already careful to not block signals that the program has asked to see. Also make sure that we don't miss a signal delivery if a thread decides to stop for a while while executing the signal handler. Also clean up the TestAtomicStop output a little bit. Fixes #21433 Change-Id: Ic0c1a4eaf7eba80d1abc1e9537570bf4687c2434 Reviewed-on: https://go-review.googlesource.com/79581 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/signal_unix.go')
-rw-r--r--src/runtime/signal_unix.go25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 9dae058f2c..e1ba2dbc78 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -526,7 +526,7 @@ func ensureSigM() {
// mask accordingly.
sigBlocked := sigset_all
for i := range sigtable {
- if sigtable[i].flags&_SigUnblock != 0 {
+ if !blockableSig(uint32(i)) {
sigdelset(&sigBlocked, i)
}
}
@@ -538,7 +538,7 @@ func ensureSigM() {
sigdelset(&sigBlocked, int(sig))
}
case sig := <-disableSigChan:
- if sig > 0 {
+ if sig > 0 && blockableSig(sig) {
sigaddset(&sigBlocked, int(sig))
}
}
@@ -736,7 +736,7 @@ func minitSignalStack() {
func minitSignalMask() {
nmask := getg().m.sigmask
for i := range sigtable {
- if sigtable[i].flags&_SigUnblock != 0 {
+ if !blockableSig(uint32(i)) {
sigdelset(&nmask, i)
}
}
@@ -757,6 +757,25 @@ func unminitSignals() {
}
}
+// blockableSig returns whether sig may be blocked by the signal mask.
+// We never want to block the signals marked _SigUnblock;
+// these are the synchronous signals that turn into a Go panic.
+// In a Go program--not a c-archive/c-shared--we never want to block
+// the signals marked _SigKill or _SigThrow, as otherwise it's possible
+// for all running threads to block them and delay their delivery until
+// we start a new thread. When linked into a C program we let the C code
+// decide on the disposition of those signals.
+func blockableSig(sig uint32) bool {
+ flags := sigtable[sig].flags
+ if flags&_SigUnblock != 0 {
+ return false
+ }
+ if isarchive || islibrary {
+ return true
+ }
+ return flags&(_SigKill|_SigThrow) == 0
+}
+
// gsignalStack saves the fields of the gsignal stack changed by
// setGsignalStack.
type gsignalStack struct {