Skip to content

Commit dfb1b69

Browse files
adam-azarchsianlancetaylor
authored andcommitted
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 37dd7cd commit dfb1b69

File tree

7 files changed

+94
-0
lines changed

7 files changed

+94
-0
lines changed

src/os/signal/signal.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ func Ignore(sig ...os.Signal) {
8686
cancel(sig, ignoreSignal)
8787
}
8888

89+
// Ignored reports whether sig is currently ignored.
90+
func Ignored(sig os.Signal) bool {
91+
if sn := signum(sig); sn < 0 {
92+
return false
93+
} else {
94+
return signalIgnored(sn)
95+
}
96+
}
97+
8998
// Notify causes package signal to relay incoming signals to c.
9099
// If no signals are provided, all incoming signals will be relayed to c.
91100
// Otherwise, just the provided signals will.

src/os/signal/signal_plan9.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var sigtab = make(map[os.Signal]int)
1515
func signal_disable(uint32)
1616
func signal_enable(uint32)
1717
func signal_ignore(uint32)
18+
func signal_ignored(uint32) bool
1819
func signal_recv() string
1920

2021
func init() {
@@ -58,3 +59,7 @@ func disableSignal(sig int) {
5859
func ignoreSignal(sig int) {
5960
signal_ignore(uint32(sig))
6061
}
62+
63+
func signalIgnored(sig int) bool {
64+
return signal_ignored(uint32(sig))
65+
}

src/os/signal/signal_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,65 @@ func TestIgnore(t *testing.T) {
192192
testCancel(t, true)
193193
}
194194

195+
// Test that Ignored correctly detects changes to the ignored status of a signal.
196+
func TestIgnored(t *testing.T) {
197+
// Ask to be notified on SIGWINCH.
198+
c := make(chan os.Signal, 1)
199+
Notify(c, syscall.SIGWINCH)
200+
201+
// If we're being notified, then the signal should not be ignored.
202+
if Ignored(syscall.SIGWINCH) {
203+
t.Errorf("expected SIGWINCH to not be ignored.")
204+
}
205+
Stop(c)
206+
Ignore(syscall.SIGWINCH)
207+
208+
// We're no longer paying attention to this signal.
209+
if !Ignored(syscall.SIGWINCH) {
210+
t.Errorf("expected SIGWINCH to be ignored when explicitly ignoring it.")
211+
}
212+
213+
Reset()
214+
}
215+
216+
var checkSighupIgnored = flag.Bool("check_sighup_ignored", false, "if true, TestDetectNohup will fail if SIGHUP is not ignored.")
217+
218+
// Test that Ignored(SIGHUP) correctly detects whether it is being run under nohup.
219+
func TestDetectNohup(t *testing.T) {
220+
if *checkSighupIgnored {
221+
if !Ignored(syscall.SIGHUP) {
222+
t.Fatal("SIGHUP is not ignored.")
223+
} else {
224+
t.Log("SIGHUP is ignored.")
225+
}
226+
} else {
227+
defer Reset()
228+
// Ugly: ask for SIGHUP so that child will not have no-hup set
229+
// even if test is running under nohup environment.
230+
// We have no intention of reading from c.
231+
c := make(chan os.Signal, 1)
232+
Notify(c, syscall.SIGHUP)
233+
if out, err := exec.Command(os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput(); err == nil {
234+
t.Errorf("ran test with -check_sighup_ignored and it succeeded: expected failure.\nOutput:\n%s", out)
235+
}
236+
Stop(c)
237+
// Again, this time with nohup, assuming we can find it.
238+
_, err := os.Stat("/usr/bin/nohup")
239+
if err != nil {
240+
t.Skip("cannot find nohup; skipping second half of test")
241+
}
242+
Ignore(syscall.SIGHUP)
243+
os.Remove("nohup.out")
244+
out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestDetectNohup", "-check_sighup_ignored").CombinedOutput()
245+
246+
data, _ := ioutil.ReadFile("nohup.out")
247+
os.Remove("nohup.out")
248+
if err != nil {
249+
t.Errorf("ran test with -check_sighup_ignored under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", err, out, data)
250+
}
251+
}
252+
}
253+
195254
var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
196255

197256
// Test that Stop cancels the channel's registrations.

src/os/signal/signal_unix.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
func signal_disable(uint32)
1616
func signal_enable(uint32)
1717
func signal_ignore(uint32)
18+
func signal_ignored(uint32) bool
1819
func signal_recv() uint32
1920

2021
func loop() {
@@ -56,3 +57,7 @@ func disableSignal(sig int) {
5657
func ignoreSignal(sig int) {
5758
signal_ignore(uint32(sig))
5859
}
60+
61+
func signalIgnored(sig int) bool {
62+
return signal_ignored(uint32(sig))
63+
}

src/runtime/signal_unix.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ func initsig(preinit bool) {
103103
// set SA_ONSTACK if necessary.
104104
if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
105105
setsigstack(i)
106+
} else if fwdSig[i] == _SIG_IGN {
107+
sigInitIgnored(i)
106108
}
107109
continue
108110
}

src/runtime/sigqueue.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,16 @@ func signal_ignore(s uint32) {
237237
atomic.Store(&sig.ignored[s/32], i)
238238
}
239239

240+
// sigInitIgnored marks the signal as already ignored. This is called at
241+
// program start by siginit.
242+
func sigInitIgnored(s uint32) {
243+
i := sig.ignored[s/32]
244+
i |= 1 << (s & 31)
245+
atomic.Store(&sig.ignored[s/32], i)
246+
}
247+
240248
// Checked by signal handlers.
249+
//go:linkname signal_ignored os/signal.signal_ignored
241250
func signal_ignored(s uint32) bool {
242251
i := atomic.Load(&sig.ignored[s/32])
243252
return i&(1<<(s&31)) != 0

src/runtime/sigqueue_plan9.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,8 @@ func signal_disable(s uint32) {
152152
//go:linkname signal_ignore os/signal.signal_ignore
153153
func signal_ignore(s uint32) {
154154
}
155+
156+
//go:linkname signal_ignored os/signal.signal_ignored
157+
func signal_ignored(s uint32) bool {
158+
return false
159+
}

0 commit comments

Comments
 (0)