mirror of
https://github.com/golang/go
synced 2024-11-18 07:04:52 -07:00
os/signal: add func Ignored(sig Signal) bool
Ignored reports whether sig is currently ignored. This implementation only works applies on Unix systems for now. However, at the moment that is also the case for Ignore() and several other signal interaction methods, so that seems fair. Fixes #22497 Change-Id: I7c1b1a5e12373ca5da44709500ff5acedc6f1316 Reviewed-on: https://go-review.googlesource.com/108376 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
37dd7cd040
commit
dfb1b69665
@ -86,6 +86,15 @@ func Ignore(sig ...os.Signal) {
|
||||
cancel(sig, ignoreSignal)
|
||||
}
|
||||
|
||||
// Ignored reports whether sig is currently ignored.
|
||||
func Ignored(sig os.Signal) bool {
|
||||
if sn := signum(sig); sn < 0 {
|
||||
return false
|
||||
} else {
|
||||
return signalIgnored(sn)
|
||||
}
|
||||
}
|
||||
|
||||
// Notify causes package signal to relay incoming signals to c.
|
||||
// If no signals are provided, all incoming signals will be relayed to c.
|
||||
// Otherwise, just the provided signals will.
|
||||
|
@ -15,6 +15,7 @@ var sigtab = make(map[os.Signal]int)
|
||||
func signal_disable(uint32)
|
||||
func signal_enable(uint32)
|
||||
func signal_ignore(uint32)
|
||||
func signal_ignored(uint32) bool
|
||||
func signal_recv() string
|
||||
|
||||
func init() {
|
||||
@ -58,3 +59,7 @@ func disableSignal(sig int) {
|
||||
func ignoreSignal(sig int) {
|
||||
signal_ignore(uint32(sig))
|
||||
}
|
||||
|
||||
func signalIgnored(sig int) bool {
|
||||
return signal_ignored(uint32(sig))
|
||||
}
|
||||
|
@ -192,6 +192,65 @@ func TestIgnore(t *testing.T) {
|
||||
testCancel(t, true)
|
||||
}
|
||||
|
||||
// Test that Ignored correctly detects changes to the ignored status of a signal.
|
||||
func TestIgnored(t *testing.T) {
|
||||
// Ask to be notified on SIGWINCH.
|
||||
c := make(chan os.Signal, 1)
|
||||
Notify(c, syscall.SIGWINCH)
|
||||
|
||||
// If we're being notified, then the signal should not be ignored.
|
||||
if Ignored(syscall.SIGWINCH) {
|
||||
t.Errorf("expected SIGWINCH to not be ignored.")
|
||||
}
|
||||
Stop(c)
|
||||
Ignore(syscall.SIGWINCH)
|
||||
|
||||
// We're no longer paying attention to this signal.
|
||||
if !Ignored(syscall.SIGWINCH) {
|
||||
t.Errorf("expected SIGWINCH to be ignored when explicitly ignoring it.")
|
||||
}
|
||||
|
||||
Reset()
|
||||
}
|
||||
|
||||
var checkSighupIgnored = flag.Bool("check_sighup_ignored", false, "if true, TestDetectNohup will fail if SIGHUP is not ignored.")
|
||||
|
||||
// Test that Ignored(SIGHUP) correctly detects whether it is being run under nohup.
|
||||
func TestDetectNohup(t *testing.T) {
|
||||
if *checkSighupIgnored {
|
||||
if !Ignored(syscall.SIGHUP) {
|
||||
t.Fatal("SIGHUP is not ignored.")
|
||||
} else {
|
||||
t.Log("SIGHUP is ignored.")
|
||||
}
|
||||
} else {
|
||||
defer Reset()
|
||||
// Ugly: ask for SIGHUP so that child will not have no-hup set
|
||||
// even if test is running under nohup environment.
|
||||
// We have no intention of reading from c.
|
||||
c := make(chan os.Signal, 1)
|
||||
Notify(c, syscall.SIGHUP)
|
||||
if out, err := exec.Command(os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput(); err == nil {
|
||||
t.Errorf("ran test with -check_sighup_ignored and it succeeded: expected failure.\nOutput:\n%s", out)
|
||||
}
|
||||
Stop(c)
|
||||
// Again, this time with nohup, assuming we can find it.
|
||||
_, err := os.Stat("/usr/bin/nohup")
|
||||
if err != nil {
|
||||
t.Skip("cannot find nohup; skipping second half of test")
|
||||
}
|
||||
Ignore(syscall.SIGHUP)
|
||||
os.Remove("nohup.out")
|
||||
out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput()
|
||||
|
||||
data, _ := ioutil.ReadFile("nohup.out")
|
||||
os.Remove("nohup.out")
|
||||
if err != nil {
|
||||
t.Errorf("ran test with -check_sighup_ignored under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", err, out, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
|
||||
|
||||
// Test that Stop cancels the channel's registrations.
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
func signal_disable(uint32)
|
||||
func signal_enable(uint32)
|
||||
func signal_ignore(uint32)
|
||||
func signal_ignored(uint32) bool
|
||||
func signal_recv() uint32
|
||||
|
||||
func loop() {
|
||||
@ -56,3 +57,7 @@ func disableSignal(sig int) {
|
||||
func ignoreSignal(sig int) {
|
||||
signal_ignore(uint32(sig))
|
||||
}
|
||||
|
||||
func signalIgnored(sig int) bool {
|
||||
return signal_ignored(uint32(sig))
|
||||
}
|
||||
|
@ -103,6 +103,8 @@ func initsig(preinit bool) {
|
||||
// set SA_ONSTACK if necessary.
|
||||
if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
|
||||
setsigstack(i)
|
||||
} else if fwdSig[i] == _SIG_IGN {
|
||||
sigInitIgnored(i)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
@ -237,7 +237,16 @@ func signal_ignore(s uint32) {
|
||||
atomic.Store(&sig.ignored[s/32], i)
|
||||
}
|
||||
|
||||
// sigInitIgnored marks the signal as already ignored. This is called at
|
||||
// program start by siginit.
|
||||
func sigInitIgnored(s uint32) {
|
||||
i := sig.ignored[s/32]
|
||||
i |= 1 << (s & 31)
|
||||
atomic.Store(&sig.ignored[s/32], i)
|
||||
}
|
||||
|
||||
// Checked by signal handlers.
|
||||
//go:linkname signal_ignored os/signal.signal_ignored
|
||||
func signal_ignored(s uint32) bool {
|
||||
i := atomic.Load(&sig.ignored[s/32])
|
||||
return i&(1<<(s&31)) != 0
|
||||
|
@ -152,3 +152,8 @@ func signal_disable(s uint32) {
|
||||
//go:linkname signal_ignore os/signal.signal_ignore
|
||||
func signal_ignore(s uint32) {
|
||||
}
|
||||
|
||||
//go:linkname signal_ignored os/signal.signal_ignored
|
||||
func signal_ignored(s uint32) bool {
|
||||
return false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user