github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/os/signal/signal_plan9_test.go (about) 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. 4 5 package signal 6 7 import ( 8 "os" 9 "runtime" 10 "syscall" 11 "testing" 12 "time" 13 ) 14 15 func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) { 16 select { 17 case s := <-c: 18 if s != sig { 19 t.Fatalf("signal was %v, want %v", s, sig) 20 } 21 case <-time.After(1 * time.Second): 22 t.Fatalf("timeout waiting for %v", sig) 23 } 24 } 25 26 // Test that basic signal handling works. 27 func TestSignal(t *testing.T) { 28 // Ask for hangup 29 c := make(chan os.Signal, 1) 30 Notify(c, syscall.Note("hangup")) 31 defer Stop(c) 32 33 // Send this process a hangup 34 t.Logf("hangup...") 35 postNote(syscall.Getpid(), "hangup") 36 waitSig(t, c, syscall.Note("hangup")) 37 38 // Ask for everything we can get. 39 c1 := make(chan os.Signal, 1) 40 Notify(c1) 41 42 // Send this process an alarm 43 t.Logf("alarm...") 44 postNote(syscall.Getpid(), "alarm") 45 waitSig(t, c1, syscall.Note("alarm")) 46 47 // Send two more hangups, to make sure that 48 // they get delivered on c1 and that not reading 49 // from c does not block everything. 50 t.Logf("hangup...") 51 postNote(syscall.Getpid(), "hangup") 52 waitSig(t, c1, syscall.Note("hangup")) 53 t.Logf("hangup...") 54 postNote(syscall.Getpid(), "hangup") 55 waitSig(t, c1, syscall.Note("hangup")) 56 57 // The first SIGHUP should be waiting for us on c. 58 waitSig(t, c, syscall.Note("hangup")) 59 } 60 61 func TestStress(t *testing.T) { 62 dur := 3 * time.Second 63 if testing.Short() { 64 dur = 100 * time.Millisecond 65 } 66 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 67 done := make(chan bool) 68 finished := make(chan bool) 69 go func() { 70 sig := make(chan os.Signal, 1) 71 Notify(sig, syscall.Note("alarm")) 72 defer Stop(sig) 73 Loop: 74 for { 75 select { 76 case <-sig: 77 case <-done: 78 break Loop 79 } 80 } 81 finished <- true 82 }() 83 go func() { 84 Loop: 85 for { 86 select { 87 case <-done: 88 break Loop 89 default: 90 postNote(syscall.Getpid(), "alarm") 91 runtime.Gosched() 92 } 93 } 94 finished <- true 95 }() 96 time.Sleep(dur) 97 close(done) 98 <-finished 99 <-finished 100 // When run with 'go test -cpu=1,2,4' alarm from this test can slip 101 // into subsequent TestSignal() causing failure. 102 // Sleep for a while to reduce the possibility of the failure. 103 time.Sleep(10 * time.Millisecond) 104 } 105 106 // Test that Stop cancels the channel's registrations. 107 func TestStop(t *testing.T) { 108 if testing.Short() { 109 t.Skip("skipping in short mode") 110 } 111 sigs := []string{ 112 "alarm", 113 "hangup", 114 } 115 116 for _, sig := range sigs { 117 // Send the signal. 118 // If it's alarm, we should not see it. 119 // If it's hangup, maybe we'll die. Let the flag tell us what to do. 120 if sig != "hangup" { 121 postNote(syscall.Getpid(), sig) 122 } 123 time.Sleep(100 * time.Millisecond) 124 125 // Ask for signal 126 c := make(chan os.Signal, 1) 127 Notify(c, syscall.Note(sig)) 128 defer Stop(c) 129 130 // Send this process that signal 131 postNote(syscall.Getpid(), sig) 132 waitSig(t, c, syscall.Note(sig)) 133 134 Stop(c) 135 select { 136 case s := <-c: 137 t.Fatalf("unexpected signal %v", s) 138 case <-time.After(100 * time.Millisecond): 139 // nothing to read - good 140 } 141 142 // Send the signal. 143 // If it's alarm, we should not see it. 144 // If it's hangup, maybe we'll die. Let the flag tell us what to do. 145 if sig != "hangup" { 146 postNote(syscall.Getpid(), sig) 147 } 148 149 select { 150 case s := <-c: 151 t.Fatalf("unexpected signal %v", s) 152 case <-time.After(100 * time.Millisecond): 153 // nothing to read - good 154 } 155 } 156 } 157 158 func itoa(val int) string { 159 if val < 0 { 160 return "-" + itoa(-val) 161 } 162 var buf [32]byte // big enough for int64 163 i := len(buf) - 1 164 for val >= 10 { 165 buf[i] = byte(val%10 + '0') 166 i-- 167 val /= 10 168 } 169 buf[i] = byte(val + '0') 170 return string(buf[i:]) 171 } 172 173 func postNote(pid int, note string) error { 174 f, err := os.OpenFile("/proc/"+itoa(pid)+"/note", os.O_WRONLY, 0) 175 if err != nil { 176 return err 177 } 178 defer f.Close() 179 _, err = f.Write([]byte(note)) 180 return err 181 }