@@ -15,8 +15,9 @@ public function testCtorAddsResourceToLoop()
1515 $ this ->markTestSkipped ('Not supported on your platform ' );
1616 }
1717
18+ $ fd = self ::getNextFreeFd ();
1819 $ socket = stream_socket_server ('127.0.0.1:0 ' );
19- $ fd = self :: getFdFromResource ( $ socket );
20+ assert ( $ socket !== false );
2021
2122 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
2223 $ loop ->expects ($ this ->once ())->method ('addReadStream ' );
@@ -48,9 +49,7 @@ public function testCtorThrowsForUnknownFd()
4849 $ this ->markTestSkipped ('Not supported on your platform ' );
4950 }
5051
51- $ socket = stream_socket_server ('127.0.0.1:0 ' );
52- $ fd = self ::getFdFromResource ($ socket );
53- fclose ($ socket );
52+ $ fd = self ::getNextFreeFd ();
5453
5554 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
5655 $ loop ->expects ($ this ->never ())->method ('addReadStream ' );
@@ -69,8 +68,9 @@ public function testCtorThrowsIfFdIsAFileAndNotASocket()
6968 $ this ->markTestSkipped ('Not supported on your platform ' );
7069 }
7170
71+ $ fd = self ::getNextFreeFd ();
7272 $ tmpfile = tmpfile ();
73- $ fd = self :: getFdFromResource ( $ tmpfile );
73+ assert ( $ tmpfile !== false );
7474
7575 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
7676 $ loop ->expects ($ this ->never ())->method ('addReadStream ' );
@@ -90,9 +90,10 @@ public function testCtorThrowsIfFdIsAConnectedSocketInsteadOfServerSocket()
9090 }
9191
9292 $ socket = stream_socket_server ('tcp://127.0.0.1:0 ' );
93- $ client = stream_socket_client ('tcp:// ' . stream_socket_get_name ($ socket , false ));
9493
95- $ fd = self ::getFdFromResource ($ client );
94+ $ fd = self ::getNextFreeFd ();
95+ $ client = stream_socket_client ('tcp:// ' . stream_socket_get_name ($ socket , false ));
96+ assert ($ client !== false );
9697
9798 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
9899 $ loop ->expects ($ this ->never ())->method ('addReadStream ' );
@@ -111,8 +112,8 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv4Socket()
111112 $ this ->markTestSkipped ('Not supported on your platform ' );
112113 }
113114
115+ $ fd = self ::getNextFreeFd ();
114116 $ socket = stream_socket_server ('127.0.0.1:0 ' );
115- $ fd = self ::getFdFromResource ($ socket );
116117
117118 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
118119
@@ -127,8 +128,8 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv4SocketGiv
127128 $ this ->markTestSkipped ('Not supported on your platform ' );
128129 }
129130
131+ $ fd = self ::getNextFreeFd ();
130132 $ socket = stream_socket_server ('127.0.0.1:0 ' );
131- $ fd = self ::getFdFromResource ($ socket );
132133
133134 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
134135
@@ -143,13 +144,12 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv6Socket()
143144 $ this ->markTestSkipped ('Not supported on your platform ' );
144145 }
145146
147+ $ fd = self ::getNextFreeFd ();
146148 $ socket = @stream_socket_server ('[::1]:0 ' );
147149 if ($ socket === false ) {
148150 $ this ->markTestSkipped ('Listening on IPv6 not supported ' );
149151 }
150152
151- $ fd = self ::getFdFromResource ($ socket );
152-
153153 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
154154
155155 $ server = new FdServer ($ fd , $ loop );
@@ -164,13 +164,12 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForUnixDomainSoc
164164 $ this ->markTestSkipped ('Not supported on your platform ' );
165165 }
166166
167+ $ fd = self ::getNextFreeFd ();
167168 $ socket = @stream_socket_server ($ this ->getRandomSocketUri ());
168169 if ($ socket === false ) {
169170 $ this ->markTestSkipped ('Listening on Unix domain socket (UDS) not supported ' );
170171 }
171172
172- $ fd = self ::getFdFromResource ($ socket );
173-
174173 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
175174
176175 $ server = new FdServer ($ fd , $ loop );
@@ -184,8 +183,9 @@ public function testGetAddressReturnsNullAfterClose()
184183 $ this ->markTestSkipped ('Not supported on your platform ' );
185184 }
186185
186+ $ fd = self ::getNextFreeFd ();
187187 $ socket = stream_socket_server ('127.0.0.1:0 ' );
188- $ fd = self :: getFdFromResource ( $ socket );
188+ assert ( $ socket !== false );
189189
190190 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
191191
@@ -201,8 +201,9 @@ public function testCloseRemovesResourceFromLoop()
201201 $ this ->markTestSkipped ('Not supported on your platform ' );
202202 }
203203
204+ $ fd = self ::getNextFreeFd ();
204205 $ socket = stream_socket_server ('127.0.0.1:0 ' );
205- $ fd = self :: getFdFromResource ( $ socket );
206+ assert ( $ socket !== false );
206207
207208 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
208209 $ loop ->expects ($ this ->once ())->method ('removeReadStream ' );
@@ -217,8 +218,9 @@ public function testCloseTwiceRemovesResourceFromLoopOnce()
217218 $ this ->markTestSkipped ('Not supported on your platform ' );
218219 }
219220
221+ $ fd = self ::getNextFreeFd ();
220222 $ socket = stream_socket_server ('127.0.0.1:0 ' );
221- $ fd = self :: getFdFromResource ( $ socket );
223+ assert ( $ socket !== false );
222224
223225 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
224226 $ loop ->expects ($ this ->once ())->method ('removeReadStream ' );
@@ -234,8 +236,9 @@ public function testResumeWithoutPauseIsNoOp()
234236 $ this ->markTestSkipped ('Not supported on your platform ' );
235237 }
236238
239+ $ fd = self ::getNextFreeFd ();
237240 $ socket = stream_socket_server ('127.0.0.1:0 ' );
238- $ fd = self :: getFdFromResource ( $ socket );
241+ assert ( $ socket !== false );
239242
240243 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
241244 $ loop ->expects ($ this ->once ())->method ('addReadStream ' );
@@ -250,8 +253,9 @@ public function testPauseRemovesResourceFromLoop()
250253 $ this ->markTestSkipped ('Not supported on your platform ' );
251254 }
252255
256+ $ fd = self ::getNextFreeFd ();
253257 $ socket = stream_socket_server ('127.0.0.1:0 ' );
254- $ fd = self :: getFdFromResource ( $ socket );
258+ assert ( $ socket !== false );
255259
256260 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
257261 $ loop ->expects ($ this ->once ())->method ('removeReadStream ' );
@@ -266,8 +270,9 @@ public function testPauseAfterPauseIsNoOp()
266270 $ this ->markTestSkipped ('Not supported on your platform ' );
267271 }
268272
273+ $ fd = self ::getNextFreeFd ();
269274 $ socket = stream_socket_server ('127.0.0.1:0 ' );
270- $ fd = self :: getFdFromResource ( $ socket );
275+ assert ( $ socket !== false );
271276
272277 $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
273278 $ loop ->expects ($ this ->once ())->method ('removeReadStream ' );
@@ -283,8 +288,9 @@ public function testServerEmitsConnectionEventForNewConnection()
283288 $ this ->markTestSkipped ('Not supported on your platform ' );
284289 }
285290
291+ $ fd = self ::getNextFreeFd ();
286292 $ socket = stream_socket_server ('127.0.0.1:0 ' );
287- $ fd = self :: getFdFromResource ( $ socket );
293+ assert ( $ socket !== false );
288294
289295 $ client = stream_socket_client ('tcp:// ' . stream_socket_get_name ($ socket , false ));
290296
@@ -313,8 +319,9 @@ public function testEmitsErrorWhenAcceptListenerFails()
313319 return true ;
314320 }));
315321
322+ $ fd = self ::getNextFreeFd ();
316323 $ socket = stream_socket_server ('127.0.0.1:0 ' );
317- $ fd = self :: getFdFromResource ( $ socket );
324+ assert ( $ socket !== false );
318325
319326 $ server = new FdServer ($ fd , $ loop );
320327
@@ -351,26 +358,25 @@ public function testEmitsTimeoutErrorWhenAcceptListenerFails(\RuntimeException $
351358 }
352359
353360 /**
354- * @param resource $resource
355361 * @return int
356362 * @throws \UnexpectedValueException
357363 * @throws \BadMethodCallException
358364 * @throws \UnderflowException
359365 * @copyright Copyright (c) 2018 Christian Lück, taken from https://github.com/clue/fd with permission
360366 */
361- public static function getFdFromResource ( $ resource )
367+ public static function getNextFreeFd ( )
362368 {
363- $ stat = @fstat ($ resource );
364- if (!isset ($ stat ['ino ' ]) || $ stat ['ino ' ] === 0 ) {
365- throw new \UnexpectedValueException ('Could not access inode of given resource (unsupported type or platform) ' );
366- }
369+ // open tmpfile to occupy next free FD temporarily
370+ $ tmp = tmpfile ();
367371
368372 $ dir = @scandir ('/dev/fd ' );
369373 if ($ dir === false ) {
370374 throw new \BadMethodCallException ('Not supported on your platform because /dev/fd is not readable ' );
371375 }
372376
377+ $ stat = fstat ($ tmp );
373378 $ ino = (int ) $ stat ['ino ' ];
379+
374380 foreach ($ dir as $ file ) {
375381 $ stat = @stat ('/dev/fd/ ' . $ file );
376382 if (isset ($ stat ['ino ' ]) && $ stat ['ino ' ] === $ ino ) {
0 commit comments