Commit 81adfa50 authored by Russ Cox's avatar Russ Cox

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/18348Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 331a6055
...@@ -151,3 +151,11 @@ func TestSignalExitStatus(t *testing.T) { ...@@ -151,3 +151,11 @@ func TestSignalExitStatus(t *testing.T) {
t.Errorf("got %v; expected SIGTERM", ee) 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)
}
}
...@@ -107,6 +107,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -139,6 +139,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -99,6 +99,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -115,6 +115,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -117,6 +117,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -121,6 +121,10 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -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 { if flags&_SigKill != 0 {
dieFromSignal(int32(sig)) dieFromSignal(int32(sig))
} }
......
...@@ -34,12 +34,13 @@ import ( ...@@ -34,12 +34,13 @@ import (
) )
var sig struct { var sig struct {
note note note note
mask [(_NSIG + 31) / 32]uint32 mask [(_NSIG + 31) / 32]uint32
wanted [(_NSIG + 31) / 32]uint32 wanted [(_NSIG + 31) / 32]uint32
recv [(_NSIG + 31) / 32]uint32 ignored [(_NSIG + 31) / 32]uint32
state uint32 recv [(_NSIG + 31) / 32]uint32
inuse bool state uint32
inuse bool
} }
const ( const (
...@@ -146,6 +147,7 @@ func signal_enable(s uint32) { ...@@ -146,6 +147,7 @@ func signal_enable(s uint32) {
return return
} }
sig.wanted[s/32] |= 1 << (s & 31) sig.wanted[s/32] |= 1 << (s & 31)
sig.ignored[s/32] &^= 1 << (s & 31)
sigenable(s) sigenable(s)
} }
...@@ -166,9 +168,15 @@ func signal_ignore(s uint32) { ...@@ -166,9 +168,15 @@ func signal_ignore(s uint32) {
return return
} }
sig.wanted[s/32] &^= 1 << (s & 31) sig.wanted[s/32] &^= 1 << (s & 31)
sig.ignored[s/32] |= 1 << (s & 31)
sigignore(s) 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. // This runs on a foreign stack, without an m or a g. No stack split.
//go:nosplit //go:nosplit
//go:norace //go:norace
......
// 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")
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment