Rebase.
[official-gcc.git] / libgo / go / os / signal / signal_test.go
blob076fe3f93bd1fcd53220e66c8dba75e218d1d071
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
7 package signal
9 import (
10 "flag"
11 "io/ioutil"
12 "os"
13 "os/exec"
14 "runtime"
15 "strconv"
16 "syscall"
17 "testing"
18 "time"
21 func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
22 select {
23 case s := <-c:
24 if s != sig {
25 t.Fatalf("signal was %v, want %v", s, sig)
27 case <-time.After(1 * time.Second):
28 t.Fatalf("timeout waiting for %v", sig)
32 // Test that basic signal handling works.
33 func TestSignal(t *testing.T) {
34 // Ask for SIGHUP
35 c := make(chan os.Signal, 1)
36 Notify(c, syscall.SIGHUP)
37 defer Stop(c)
39 // Send this process a SIGHUP
40 t.Logf("sighup...")
41 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
42 waitSig(t, c, syscall.SIGHUP)
44 // Ask for everything we can get.
45 c1 := make(chan os.Signal, 1)
46 Notify(c1)
48 // Send this process a SIGWINCH
49 t.Logf("sigwinch...")
50 syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
51 waitSig(t, c1, syscall.SIGWINCH)
53 // Send two more SIGHUPs, to make sure that
54 // they get delivered on c1 and that not reading
55 // from c does not block everything.
56 t.Logf("sighup...")
57 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
58 waitSig(t, c1, syscall.SIGHUP)
59 t.Logf("sighup...")
60 syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
61 waitSig(t, c1, syscall.SIGHUP)
63 // The first SIGHUP should be waiting for us on c.
64 waitSig(t, c, syscall.SIGHUP)
67 func TestStress(t *testing.T) {
68 dur := 3 * time.Second
69 if testing.Short() {
70 dur = 100 * time.Millisecond
72 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
73 done := make(chan bool)
74 finished := make(chan bool)
75 go func() {
76 sig := make(chan os.Signal, 1)
77 Notify(sig, syscall.SIGUSR1)
78 defer Stop(sig)
79 Loop:
80 for {
81 select {
82 case <-sig:
83 case <-done:
84 break Loop
87 finished <- true
88 }()
89 go func() {
90 Loop:
91 for {
92 select {
93 case <-done:
94 break Loop
95 default:
96 syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
97 runtime.Gosched()
100 finished <- true
102 time.Sleep(dur)
103 close(done)
104 <-finished
105 <-finished
106 // When run with 'go test -cpu=1,2,4' SIGUSR1 from this test can slip
107 // into subsequent TestSignal() causing failure.
108 // Sleep for a while to reduce the possibility of the failure.
109 time.Sleep(10 * time.Millisecond)
112 var sendUncaughtSighup = flag.Int("send_uncaught_sighup", 0, "send uncaught SIGHUP during TestStop")
114 // Test that Stop cancels the channel's registrations.
115 func TestStop(t *testing.T) {
116 sigs := []syscall.Signal{
117 syscall.SIGWINCH,
118 syscall.SIGHUP,
121 for _, sig := range sigs {
122 // Send the signal.
123 // If it's SIGWINCH, we should not see it.
124 // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
125 if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 {
126 syscall.Kill(syscall.Getpid(), sig)
128 time.Sleep(10 * time.Millisecond)
130 // Ask for signal
131 c := make(chan os.Signal, 1)
132 Notify(c, sig)
133 defer Stop(c)
135 // Send this process that signal
136 syscall.Kill(syscall.Getpid(), sig)
137 waitSig(t, c, sig)
139 Stop(c)
140 select {
141 case s := <-c:
142 t.Fatalf("unexpected signal %v", s)
143 case <-time.After(10 * time.Millisecond):
144 // nothing to read - good
147 // Send the signal.
148 // If it's SIGWINCH, we should not see it.
149 // If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
150 if sig != syscall.SIGHUP || *sendUncaughtSighup == 2 {
151 syscall.Kill(syscall.Getpid(), sig)
154 select {
155 case s := <-c:
156 t.Fatalf("unexpected signal %v", s)
157 case <-time.After(10 * time.Millisecond):
158 // nothing to read - good
163 // Test that when run under nohup, an uncaught SIGHUP does not kill the program,
164 // but a
165 func TestNohup(t *testing.T) {
166 // Ugly: ask for SIGHUP so that child will not have no-hup set
167 // even if test is running under nohup environment.
168 // We have no intention of reading from c.
169 c := make(chan os.Signal, 1)
170 Notify(c, syscall.SIGHUP)
172 // When run without nohup, the test should crash on an uncaught SIGHUP.
173 // When run under nohup, the test should ignore uncaught SIGHUPs,
174 // because the runtime is not supposed to be listening for them.
175 // Either way, TestStop should still be able to catch them when it wants them
176 // and then when it stops wanting them, the original behavior should resume.
178 // send_uncaught_sighup=1 sends the SIGHUP before starting to listen for SIGHUPs.
179 // send_uncaught_sighup=2 sends the SIGHUP after no longer listening for SIGHUPs.
181 // Both should fail without nohup and succeed with nohup.
183 for i := 1; i <= 2; i++ {
184 out, err := exec.Command(os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
185 if err == nil {
186 t.Fatalf("ran test with -send_uncaught_sighup=%d and it succeeded: expected failure.\nOutput:\n%s", i, out)
190 Stop(c)
192 // Again, this time with nohup, assuming we can find it.
193 _, err := os.Stat("/usr/bin/nohup")
194 if err != nil {
195 t.Skip("cannot find nohup; skipping second half of test")
198 for i := 1; i <= 2; i++ {
199 os.Remove("nohup.out")
200 out, err := exec.Command("/usr/bin/nohup", os.Args[0], "-test.run=TestStop", "-send_uncaught_sighup="+strconv.Itoa(i)).CombinedOutput()
202 data, _ := ioutil.ReadFile("nohup.out")
203 os.Remove("nohup.out")
204 if err != nil {
205 t.Fatalf("ran test with -send_uncaught_sighup=%d under nohup and it failed: expected success.\nError: %v\nOutput:\n%s%s", i, err, out, data)