From 81adfa508a81e24b8257571dd717845647607cbd Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 7 Jan 2016 10:19:55 -0500 Subject: [PATCH] runtime: allow signal.Ignore of user-generated throwing signals Today, signal.Ignore(syscall.SIGTRAP) does nothing while signal.Notify(make(chan os.Signal), syscall.SIGTRAP) correctly discards user-generated SIGTRAPs. The same applies to any signal that we throw on. Make signal.Ignore work for these signals. Fixes #12906. Change-Id: Iba244813051e0ce23fa32fbad3e3fa596a941094 Reviewed-on: https://go-review.googlesource.com/18348 Reviewed-by: Ian Lance Taylor Run-TryBot: Russ Cox TryBot-Result: Gobot Gobot --- src/runtime/crash_unix_test.go | 8 +++++++ src/runtime/signal_386.go | 4 ++++ src/runtime/signal_amd64x.go | 4 ++++ src/runtime/signal_arm.go | 4 ++++ src/runtime/signal_arm64.go | 4 ++++ src/runtime/signal_mips64x.go | 4 ++++ src/runtime/signal_ppc64x.go | 4 ++++ src/runtime/sigqueue.go | 20 ++++++++++++----- src/runtime/testdata/testprognet/signal.go | 26 ++++++++++++++++++++++ 9 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 src/runtime/testdata/testprognet/signal.go diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 59425271c5..a7af7eff28 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -151,3 +151,11 @@ func TestSignalExitStatus(t *testing.T) { t.Errorf("got %v; expected SIGTERM", ee) } } + +func TestSignalIgnoreSIGTRAP(t *testing.T) { + output := runTestProg(t, "testprognet", "SignalIgnoreSIGTRAP") + want := "OK\n" + if output != want { + t.Fatalf("want %s, got %s\n", want, output) + } +} diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go index 5c53582f90..0374f4a2d7 100644 --- a/src/runtime/signal_386.go +++ b/src/runtime/signal_386.go @@ -107,6 +107,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/signal_amd64x.go b/src/runtime/signal_amd64x.go index 834e85563c..0f6700dbf1 100644 --- a/src/runtime/signal_amd64x.go +++ b/src/runtime/signal_amd64x.go @@ -139,6 +139,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go index 9ea48dff8a..3ea3938e59 100644 --- a/src/runtime/signal_arm.go +++ b/src/runtime/signal_arm.go @@ -99,6 +99,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go index 9a83bf0c97..e647c76850 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -115,6 +115,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 868e993104..77c27148e8 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -117,6 +117,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go index ee263484aa..1c868b84a1 100644 --- a/src/runtime/signal_ppc64x.go +++ b/src/runtime/signal_ppc64x.go @@ -121,6 +121,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { } } + if c.sigcode() == _SI_USER && signal_ignored(sig) { + return + } + if flags&_SigKill != 0 { dieFromSignal(int32(sig)) } diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go index 8c9951ae1d..84616ebceb 100644 --- a/src/runtime/sigqueue.go +++ b/src/runtime/sigqueue.go @@ -34,12 +34,13 @@ import ( ) var sig struct { - note note - mask [(_NSIG + 31) / 32]uint32 - wanted [(_NSIG + 31) / 32]uint32 - recv [(_NSIG + 31) / 32]uint32 - state uint32 - inuse bool + note note + mask [(_NSIG + 31) / 32]uint32 + wanted [(_NSIG + 31) / 32]uint32 + ignored [(_NSIG + 31) / 32]uint32 + recv [(_NSIG + 31) / 32]uint32 + state uint32 + inuse bool } const ( @@ -146,6 +147,7 @@ func signal_enable(s uint32) { return } sig.wanted[s/32] |= 1 << (s & 31) + sig.ignored[s/32] &^= 1 << (s & 31) sigenable(s) } @@ -166,9 +168,15 @@ func signal_ignore(s uint32) { return } sig.wanted[s/32] &^= 1 << (s & 31) + sig.ignored[s/32] |= 1 << (s & 31) sigignore(s) } +// Checked by signal handlers. +func signal_ignored(s uint32) bool { + return sig.ignored[s/32]&(1<<(s&31)) != 0 +} + // This runs on a foreign stack, without an m or a g. No stack split. //go:nosplit //go:norace diff --git a/src/runtime/testdata/testprognet/signal.go b/src/runtime/testdata/testprognet/signal.go new file mode 100644 index 0000000000..24d142403e --- /dev/null +++ b/src/runtime/testdata/testprognet/signal.go @@ -0,0 +1,26 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !windows,!plan9,!nacl + +// This is in testprognet instead of testprog because testprog +// must not import anything (like net, but also like os/signal) +// that kicks off background goroutines during init. + +package main + +import ( + "os/signal" + "syscall" +) + +func init() { + register("SignalIgnoreSIGTRAP", SignalIgnoreSIGTRAP) +} + +func SignalIgnoreSIGTRAP() { + signal.Ignore(syscall.SIGTRAP) + syscall.Kill(syscall.Getpid(), syscall.SIGTRAP) + println("OK") +} -- 2.50.0