@@ -18,6 +18,40 @@ import (
18
18
"golang.org/x/sys/unix"
19
19
)
20
20
21
+ // getOneRetry wraps EventPort.GetOne which in turn wraps a syscall that can be
22
+ // interrupted causing us to receive EINTR.
23
+ // To prevent our tests from flaking, we retry the syscall until it works
24
+ // rather than get unexpected results in our tests.
25
+ func getOneRetry (t * testing.T , p * unix.EventPort , timeout * unix.Timespec ) (e * unix.PortEvent , err error ) {
26
+ t .Helper ()
27
+ for {
28
+ e , err = p .GetOne (timeout )
29
+ if err != unix .EINTR {
30
+ break
31
+ }
32
+ }
33
+ return e , err
34
+ }
35
+
36
+ // getRetry wraps EventPort.Get which in turn wraps a syscall that can be
37
+ // interrupted causing us to receive EINTR.
38
+ // To prevent our tests from flaking, we retry the syscall until it works
39
+ // rather than get unexpected results in our tests.
40
+ func getRetry (t * testing.T , p * unix.EventPort , s []unix.PortEvent , min int , timeout * unix.Timespec ) (n int , err error ) {
41
+ t .Helper ()
42
+ for {
43
+ n , err = p .Get (s , min , timeout )
44
+ if err != unix .EINTR {
45
+ break
46
+ }
47
+ // If we did get EINTR, make sure we got 0 events
48
+ if n != 0 {
49
+ t .Fatalf ("EventPort.Get returned events on EINTR.\n got: %d\n expected: 0" , n )
50
+ }
51
+ }
52
+ return n , err
53
+ }
54
+
21
55
func TestStatvfs (t * testing.T ) {
22
56
if err := unix .Statvfs ("" , nil ); err == nil {
23
57
t .Fatal (`Statvfs("") expected failure` )
@@ -84,13 +118,13 @@ func TestBasicEventPort(t *testing.T) {
84
118
bs := []byte {42 }
85
119
tmpfile .Write (bs )
86
120
timeout := new (unix.Timespec )
87
- timeout .Sec = 1
88
- pevent , err := port . GetOne ( timeout )
121
+ timeout .Nsec = 100
122
+ pevent , err := getOneRetry ( t , port , timeout )
89
123
if err == unix .ETIME {
90
124
t .Errorf ("GetOne timed out: %v" , err )
91
125
}
92
126
if err != nil {
93
- t .Errorf ("GetOne failed: %v" , err )
127
+ t .Fatalf ("GetOne failed: %v" , err )
94
128
}
95
129
if pevent .Path != path {
96
130
t .Errorf ("Path mismatch: %v != %v" , pevent .Path , path )
@@ -135,13 +169,13 @@ func TestEventPortFds(t *testing.T) {
135
169
t .Errorf ("Pending() failed: %v, %v" , n , err )
136
170
}
137
171
timeout := new (unix.Timespec )
138
- timeout .Sec = 1
139
- pevent , err := port . GetOne ( timeout )
172
+ timeout .Nsec = 100
173
+ pevent , err := getOneRetry ( t , port , timeout )
140
174
if err == unix .ETIME {
141
175
t .Errorf ("GetOne timed out: %v" , err )
142
176
}
143
177
if err != nil {
144
- t .Errorf ("GetOne failed: %v" , err )
178
+ t .Fatalf ("GetOne failed: %v" , err )
145
179
}
146
180
if pevent .Fd != fd {
147
181
t .Errorf ("Fd mismatch: %v != %v" , pevent .Fd , fd )
@@ -181,26 +215,24 @@ func TestEventPortErrors(t *testing.T) {
181
215
}
182
216
timeout := new (unix.Timespec )
183
217
timeout .Nsec = 1
184
- _ , err = port . GetOne ( timeout )
218
+ _ , err = getOneRetry ( t , port , timeout )
185
219
if err != unix .ETIME {
186
- // See https://go.dev/issue/58259
187
- // Perhaps we sometimes get EINTR ???
188
220
t .Errorf ("port.GetOne(%v) returned error %v, want %v" , timeout , err , unix .ETIME )
189
221
}
190
222
err = port .DissociateFd (uintptr (0 ))
191
223
if err == nil {
192
224
t .Errorf ("unexpected success dissociating unassociated fd" )
193
225
}
194
226
events := make ([]unix.PortEvent , 4 )
195
- _ , err = port . Get ( events , 5 , nil )
227
+ _ , err = getRetry ( t , port , events , 5 , nil )
196
228
if err == nil {
197
229
t .Errorf ("unexpected success calling Get with min greater than len of slice" )
198
230
}
199
- _ , err = port . Get ( nil , 1 , nil )
231
+ _ , err = getRetry ( t , port , nil , 1 , nil )
200
232
if err == nil {
201
233
t .Errorf ("unexpected success calling Get with nil slice" )
202
234
}
203
- _ , err = port . Get ( nil , 0 , nil )
235
+ _ , err = getRetry ( t , port , nil , 0 , nil )
204
236
if err == nil {
205
237
t .Errorf ("unexpected success calling Get with nil slice" )
206
238
}
@@ -232,7 +264,13 @@ func ExamplePortEvent() {
232
264
w .Write (bs )
233
265
timeout := new (unix.Timespec )
234
266
timeout .Sec = 1
235
- pevent , err := port .GetOne (timeout )
267
+ var pevent * unix.PortEvent
268
+ for {
269
+ pevent , err = port .GetOne (timeout )
270
+ if err != unix .EINTR {
271
+ break
272
+ }
273
+ }
236
274
if err != nil {
237
275
fmt .Printf ("didn't get the expected event: %v\n " , err )
238
276
}
@@ -278,7 +316,7 @@ func TestPortEventSlices(t *testing.T) {
278
316
timeout := new (unix.Timespec )
279
317
timeout .Nsec = 1
280
318
events := make ([]unix.PortEvent , 4 )
281
- n , err = port . Get ( events , 3 , timeout )
319
+ n , err = getRetry ( t , port , events , 3 , timeout )
282
320
if err != nil {
283
321
t .Errorf ("Get failed: %v" , err )
284
322
}
@@ -291,7 +329,7 @@ func TestPortEventSlices(t *testing.T) {
291
329
t .Errorf ("unexpected event. got %v, expected %v" , p .Events , unix .FILE_DELETE )
292
330
}
293
331
}
294
- n , err = port . Get ( events , 3 , timeout )
332
+ n , err = getRetry ( t , port , events , 3 , timeout )
295
333
if err != unix .ETIME {
296
334
t .Errorf ("unexpected error. got %v, expected %v" , err , unix .ETIME )
297
335
}
@@ -314,7 +352,7 @@ func TestPortEventSlices(t *testing.T) {
314
352
bs := []byte {41 }
315
353
w .Write (bs )
316
354
317
- n , err = port . Get ( events , 1 , timeout )
355
+ n , err = getRetry ( t , port , events , 1 , timeout )
318
356
if err != nil {
319
357
t .Errorf ("Get failed: %v" , err )
320
358
}
0 commit comments