Skip to content

Commit 0b2d959

Browse files
committed
Explicitly forward warnings to any registered error handlers
1 parent bc0bca9 commit 0b2d959

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

src/StreamSelectLoop.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,28 @@ private function streamSelect(array &$read, array &$write, $timeout)
287287
}
288288
}
289289

290-
// suppress warnings that occur when `stream_select()` is interrupted by a signal
291-
\set_error_handler(function ($errno, $errstr) {
290+
/** @var ?callable $previous */
291+
$previous = \set_error_handler(function ($errno, $errstr) use (&$previous) {
292+
// suppress warnings that occur when `stream_select()` is interrupted by a signal
292293
$eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : 4;
293-
return ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false);
294-
});
294+
if ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false) {
295+
return;
296+
}
295297

296-
$ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
298+
// forward any other error to registered error handler or print warning
299+
return ($previous !== null) ? \call_user_func_array($previous, \func_get_args()) : false;
300+
});
297301

298-
\restore_error_handler();
302+
try {
303+
$ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
304+
\restore_error_handler();
305+
} catch (\Throwable $e) { // @codeCoverageIgnoreStart
306+
\restore_error_handler();
307+
throw $e;
308+
} catch (\Exception $e) {
309+
\restore_error_handler();
310+
throw $e;
311+
} // @codeCoverageIgnoreEnd
299312

300313
if ($except) {
301314
$write = \array_merge($write, $except);

tests/StreamSelectLoopTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,77 @@ public function testStreamSelectTimeoutEmulation()
4040
$this->assertGreaterThan(0.04, $interval);
4141
}
4242

43+
public function testStreamSelectReportsWarningForStreamWithFilter()
44+
{
45+
$stream = tmpfile();
46+
stream_filter_append($stream, 'string.rot13');
47+
48+
$this->loop->addReadStream($stream, $this->expectCallableNever());
49+
50+
$loop = $this->loop;
51+
$this->loop->futureTick(function () use ($loop, $stream) {
52+
$loop->futureTick(function () use ($loop, $stream) {
53+
$loop->removeReadStream($stream);
54+
});
55+
});
56+
57+
$error = null;
58+
$previous = set_error_handler(function ($_, $errstr) use (&$error) {
59+
$error = $errstr;
60+
});
61+
62+
try {
63+
$this->loop->run();
64+
} catch (\ValueError $e) {
65+
// ignore ValueError for PHP 8+ due to empty stream array
66+
}
67+
68+
restore_error_handler();
69+
70+
$this->assertNotNull($error);
71+
72+
$now = set_error_handler(function () { });
73+
restore_error_handler();
74+
$this->assertEquals($previous, $now);
75+
}
76+
77+
public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithFilter()
78+
{
79+
$stream = tmpfile();
80+
stream_filter_append($stream, 'string.rot13');
81+
82+
$this->loop->addReadStream($stream, $this->expectCallableNever());
83+
84+
$loop = $this->loop;
85+
$this->loop->futureTick(function () use ($loop, $stream) {
86+
$loop->futureTick(function () use ($loop, $stream) {
87+
$loop->removeReadStream($stream);
88+
});
89+
});
90+
91+
$previous = set_error_handler(function ($_, $errstr) {
92+
throw new \RuntimeException($errstr);
93+
});
94+
95+
$e = null;
96+
try {
97+
$this->loop->run();
98+
restore_error_handler();
99+
$this->fail();
100+
} catch (\RuntimeException $e) {
101+
restore_error_handler();
102+
} catch (\ValueError $e) {
103+
restore_error_handler(); // PHP 8+
104+
$e = $e->getPrevious();
105+
}
106+
107+
$this->assertInstanceOf('RuntimeException', $e);
108+
109+
$now = set_error_handler(function () { });
110+
restore_error_handler();
111+
$this->assertEquals($previous, $now);
112+
}
113+
43114
public function signalProvider()
44115
{
45116
return array(

0 commit comments

Comments
 (0)