@@ -36,14 +36,15 @@ import (
36
36
"net"
37
37
"os"
38
38
"os/exec"
39
+ "os/signal"
39
40
"sync"
40
41
"syscall"
41
42
"time"
42
43
)
43
44
44
45
func init () {
45
46
register ("EINTR" , EINTR )
46
- register ("Nop " , Nop )
47
+ register ("Block " , Block )
47
48
}
48
49
49
50
// Test various operations when a signal handler is installed without
@@ -59,13 +60,6 @@ func EINTR() {
59
60
log .Fatal (syscall .Errno (errno ))
60
61
}
61
62
62
- // Send ourselves SIGWINCH regularly.
63
- go func () {
64
- for range time .Tick (100 * time .Microsecond ) {
65
- syscall .Kill (0 , syscall .SIGWINCH )
66
- }
67
- }()
68
-
69
63
var wg sync.WaitGroup
70
64
testPipe (& wg )
71
65
testNet (& wg )
@@ -90,6 +84,22 @@ func spin() (float64, [][]byte) {
90
84
return r1 , r2
91
85
}
92
86
87
+ // winch sends a few SIGWINCH signals to the process.
88
+ func winch () {
89
+ ticker := time .NewTicker (100 * time .Microsecond )
90
+ defer ticker .Stop ()
91
+ for n := 10 ; n > 0 ; n -- {
92
+ syscall .Kill (0 , syscall .SIGWINCH )
93
+ <- ticker .C
94
+ }
95
+ }
96
+
97
+ // sendSomeSignals triggers a few SIGURG and SIGWINCH signals.
98
+ func sendSomeSignals () {
99
+ spin ()
100
+ winch ()
101
+ }
102
+
93
103
// testPipe tests pipe operations.
94
104
func testPipe (wg * sync.WaitGroup ) {
95
105
r , w , err := os .Pipe ()
@@ -109,19 +119,19 @@ func testPipe(wg *sync.WaitGroup) {
109
119
// Spin before calling Write so that the first ReadFull
110
120
// in the other goroutine will likely be interrupted
111
121
// by a signal.
112
- spin ()
122
+ sendSomeSignals ()
113
123
// This Write will likely be interrupted by a signal
114
124
// as the other goroutine spins in the middle of reading.
115
125
// We write enough data that we should always fill the
116
126
// pipe buffer and need multiple write system calls.
117
- if _ , err := w .Write (bytes .Repeat ([]byte {0 }, 2 << 20 )); err != nil {
127
+ if _ , err := w .Write (bytes .Repeat ([]byte {0 }, 2 << 20 )); err != nil {
118
128
log .Fatal (err )
119
129
}
120
130
}()
121
131
go func () {
122
132
defer wg .Done ()
123
133
defer r .Close ()
124
- b := make ([]byte , 1 << 20 )
134
+ b := make ([]byte , 1 << 20 )
125
135
// This ReadFull will likely be interrupted by a signal,
126
136
// as the other goroutine spins before writing anything.
127
137
if _ , err := io .ReadFull (r , b ); err != nil {
@@ -130,7 +140,7 @@ func testPipe(wg *sync.WaitGroup) {
130
140
// Spin after reading half the data so that the Write
131
141
// in the other goroutine will likely be interrupted
132
142
// before it completes.
133
- spin ()
143
+ sendSomeSignals ()
134
144
if _ , err := io .ReadFull (r , b ); err != nil {
135
145
log .Fatal (err )
136
146
}
@@ -164,14 +174,14 @@ func testNet(wg *sync.WaitGroup) {
164
174
log .Fatal (err )
165
175
}
166
176
// See comments in testPipe.
167
- spin ()
168
- if _ , err := cf .Write (bytes .Repeat ([]byte {0 }, 2 << 20 )); err != nil {
177
+ sendSomeSignals ()
178
+ if _ , err := cf .Write (bytes .Repeat ([]byte {0 }, 2 << 20 )); err != nil {
169
179
log .Fatal (err )
170
180
}
171
181
}()
172
182
go func () {
173
183
defer wg .Done ()
174
- spin ()
184
+ sendSomeSignals ()
175
185
c , err := net .Dial ("tcp" , ln .Addr ().String ())
176
186
if err != nil {
177
187
log .Fatal (err )
@@ -186,11 +196,11 @@ func testNet(wg *sync.WaitGroup) {
186
196
log .Fatal (err )
187
197
}
188
198
// See comments in testPipe.
189
- b := make ([]byte , 1 << 20 )
199
+ b := make ([]byte , 1 << 20 )
190
200
if _ , err := io .ReadFull (cf , b ); err != nil {
191
201
log .Fatal (err )
192
202
}
193
- spin ()
203
+ sendSomeSignals ()
194
204
if _ , err := io .ReadFull (cf , b ); err != nil {
195
205
log .Fatal (err )
196
206
}
@@ -201,14 +211,30 @@ func testExec(wg *sync.WaitGroup) {
201
211
wg .Add (1 )
202
212
go func () {
203
213
defer wg .Done ()
204
- if err := exec .Command (os .Args [0 ], "Nop" ).Run (); err != nil {
214
+ cmd := exec .Command (os .Args [0 ], "Block" )
215
+ cmd .Stderr = new (bytes.Buffer )
216
+ cmd .Stdout = cmd .Stderr
217
+ if err := cmd .Start (); err != nil {
205
218
log .Fatal (err )
206
219
}
220
+
221
+ go func () {
222
+ sendSomeSignals ()
223
+ if err := cmd .Process .Signal (os .Interrupt ); err != nil {
224
+ panic (err )
225
+ }
226
+ }()
227
+
228
+ if err := cmd .Wait (); err != nil {
229
+ log .Fatalf ("%v:\n %s" , err , cmd .Stdout )
230
+ }
207
231
}()
208
232
}
209
233
210
- // Nop just sleeps for a bit. This is used to test interrupts while waiting
211
- // for a child.
212
- func Nop () {
213
- time .Sleep (time .Millisecond )
234
+ // Block blocks until the process receives os.Interrupt.
235
+ func Block () {
236
+ c := make (chan os.Signal , 1 )
237
+ signal .Notify (c , os .Interrupt )
238
+ defer signal .Stop (c )
239
+ <- c
214
240
}
0 commit comments