@@ -18,6 +18,40 @@ import (
1818 "golang.org/x/sys/unix"
1919)
2020
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+
2155func TestStatvfs (t * testing.T ) {
2256 if err := unix .Statvfs ("" , nil ); err == nil {
2357 t .Fatal (`Statvfs("") expected failure` )
@@ -84,13 +118,13 @@ func TestBasicEventPort(t *testing.T) {
84118 bs := []byte {42 }
85119 tmpfile .Write (bs )
86120 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 )
89123 if err == unix .ETIME {
90124 t .Errorf ("GetOne timed out: %v" , err )
91125 }
92126 if err != nil {
93- t .Errorf ("GetOne failed: %v" , err )
127+ t .Fatalf ("GetOne failed: %v" , err )
94128 }
95129 if pevent .Path != path {
96130 t .Errorf ("Path mismatch: %v != %v" , pevent .Path , path )
@@ -135,13 +169,13 @@ func TestEventPortFds(t *testing.T) {
135169 t .Errorf ("Pending() failed: %v, %v" , n , err )
136170 }
137171 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 )
140174 if err == unix .ETIME {
141175 t .Errorf ("GetOne timed out: %v" , err )
142176 }
143177 if err != nil {
144- t .Errorf ("GetOne failed: %v" , err )
178+ t .Fatalf ("GetOne failed: %v" , err )
145179 }
146180 if pevent .Fd != fd {
147181 t .Errorf ("Fd mismatch: %v != %v" , pevent .Fd , fd )
@@ -181,26 +215,24 @@ func TestEventPortErrors(t *testing.T) {
181215 }
182216 timeout := new (unix.Timespec )
183217 timeout .Nsec = 1
184- _ , err = port . GetOne ( timeout )
218+ _ , err = getOneRetry ( t , port , timeout )
185219 if err != unix .ETIME {
186- // See https://go.dev/issue/58259
187- // Perhaps we sometimes get EINTR ???
188220 t .Errorf ("port.GetOne(%v) returned error %v, want %v" , timeout , err , unix .ETIME )
189221 }
190222 err = port .DissociateFd (uintptr (0 ))
191223 if err == nil {
192224 t .Errorf ("unexpected success dissociating unassociated fd" )
193225 }
194226 events := make ([]unix.PortEvent , 4 )
195- _ , err = port . Get ( events , 5 , nil )
227+ _ , err = getRetry ( t , port , events , 5 , nil )
196228 if err == nil {
197229 t .Errorf ("unexpected success calling Get with min greater than len of slice" )
198230 }
199- _ , err = port . Get ( nil , 1 , nil )
231+ _ , err = getRetry ( t , port , nil , 1 , nil )
200232 if err == nil {
201233 t .Errorf ("unexpected success calling Get with nil slice" )
202234 }
203- _ , err = port . Get ( nil , 0 , nil )
235+ _ , err = getRetry ( t , port , nil , 0 , nil )
204236 if err == nil {
205237 t .Errorf ("unexpected success calling Get with nil slice" )
206238 }
@@ -232,7 +264,13 @@ func ExamplePortEvent() {
232264 w .Write (bs )
233265 timeout := new (unix.Timespec )
234266 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+ }
236274 if err != nil {
237275 fmt .Printf ("didn't get the expected event: %v\n " , err )
238276 }
@@ -278,7 +316,7 @@ func TestPortEventSlices(t *testing.T) {
278316 timeout := new (unix.Timespec )
279317 timeout .Nsec = 1
280318 events := make ([]unix.PortEvent , 4 )
281- n , err = port . Get ( events , 3 , timeout )
319+ n , err = getRetry ( t , port , events , 3 , timeout )
282320 if err != nil {
283321 t .Errorf ("Get failed: %v" , err )
284322 }
@@ -291,7 +329,7 @@ func TestPortEventSlices(t *testing.T) {
291329 t .Errorf ("unexpected event. got %v, expected %v" , p .Events , unix .FILE_DELETE )
292330 }
293331 }
294- n , err = port . Get ( events , 3 , timeout )
332+ n , err = getRetry ( t , port , events , 3 , timeout )
295333 if err != unix .ETIME {
296334 t .Errorf ("unexpected error. got %v, expected %v" , err , unix .ETIME )
297335 }
@@ -314,7 +352,7 @@ func TestPortEventSlices(t *testing.T) {
314352 bs := []byte {41 }
315353 w .Write (bs )
316354
317- n , err = port . Get ( events , 1 , timeout )
355+ n , err = getRetry ( t , port , events , 1 , timeout )
318356 if err != nil {
319357 t .Errorf ("Get failed: %v" , err )
320358 }
0 commit comments