From bc0bca9c6d88320d552fecd6d5e755ca081fb6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Thu, 17 Feb 2022 15:50:48 +0100 Subject: [PATCH 1/2] Do not suppress warnings for invalid streams in `stream_select()` --- src/StreamSelectLoop.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 4b1f81c1..14a2613f 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -287,8 +287,15 @@ private function streamSelect(array &$read, array &$write, $timeout) } } - // suppress warnings that occur, when stream_select is interrupted by a signal - $ret = @\stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); + // suppress warnings that occur when `stream_select()` is interrupted by a signal + \set_error_handler(function ($errno, $errstr) { + $eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : 4; + return ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false); + }); + + $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); + + \restore_error_handler(); if ($except) { $write = \array_merge($write, $except); From 2c8533c82a18a206ec829d85497957ccd824c0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Fri, 18 Feb 2022 15:38:25 +0100 Subject: [PATCH 2/2] Explicitly forward warnings to any registered error handlers --- src/StreamSelectLoop.php | 25 ++++++++--- tests/StreamSelectLoopTest.php | 79 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/src/StreamSelectLoop.php b/src/StreamSelectLoop.php index 14a2613f..9e78dc03 100644 --- a/src/StreamSelectLoop.php +++ b/src/StreamSelectLoop.php @@ -287,15 +287,28 @@ private function streamSelect(array &$read, array &$write, $timeout) } } - // suppress warnings that occur when `stream_select()` is interrupted by a signal - \set_error_handler(function ($errno, $errstr) { + /** @var ?callable $previous */ + $previous = \set_error_handler(function ($errno, $errstr) use (&$previous) { + // suppress warnings that occur when `stream_select()` is interrupted by a signal $eintr = \defined('SOCKET_EINTR') ? \SOCKET_EINTR : 4; - return ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false); - }); + if ($errno === \E_WARNING && \strpos($errstr, '[' . $eintr .']: ') !== false) { + return; + } - $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); + // forward any other error to registered error handler or print warning + return ($previous !== null) ? \call_user_func_array($previous, \func_get_args()) : false; + }); - \restore_error_handler(); + try { + $ret = \stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout); + \restore_error_handler(); + } catch (\Throwable $e) { // @codeCoverageIgnoreStart + \restore_error_handler(); + throw $e; + } catch (\Exception $e) { + \restore_error_handler(); + throw $e; + } // @codeCoverageIgnoreEnd if ($except) { $write = \array_merge($write, $except); diff --git a/tests/StreamSelectLoopTest.php b/tests/StreamSelectLoopTest.php index d6800c5e..80197468 100644 --- a/tests/StreamSelectLoopTest.php +++ b/tests/StreamSelectLoopTest.php @@ -40,6 +40,85 @@ public function testStreamSelectTimeoutEmulation() $this->assertGreaterThan(0.04, $interval); } + public function testStreamSelectReportsWarningForStreamWithFilter() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Not supported on legacy HHVM'); + } + + $stream = tmpfile(); + stream_filter_append($stream, 'string.rot13'); + + $this->loop->addReadStream($stream, $this->expectCallableNever()); + + $loop = $this->loop; + $this->loop->futureTick(function () use ($loop, $stream) { + $loop->futureTick(function () use ($loop, $stream) { + $loop->removeReadStream($stream); + }); + }); + + $error = null; + $previous = set_error_handler(function ($_, $errstr) use (&$error) { + $error = $errstr; + }); + + try { + $this->loop->run(); + } catch (\ValueError $e) { + // ignore ValueError for PHP 8+ due to empty stream array + } + + restore_error_handler(); + + $this->assertNotNull($error); + + $now = set_error_handler(function () { }); + restore_error_handler(); + $this->assertEquals($previous, $now); + } + + public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithFilter() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('Not supported on legacy HHVM'); + } + + $stream = tmpfile(); + stream_filter_append($stream, 'string.rot13'); + + $this->loop->addReadStream($stream, $this->expectCallableNever()); + + $loop = $this->loop; + $this->loop->futureTick(function () use ($loop, $stream) { + $loop->futureTick(function () use ($loop, $stream) { + $loop->removeReadStream($stream); + }); + }); + + $previous = set_error_handler(function ($_, $errstr) { + throw new \RuntimeException($errstr); + }); + + $e = null; + try { + $this->loop->run(); + restore_error_handler(); + $this->fail(); + } catch (\RuntimeException $e) { + restore_error_handler(); + } catch (\ValueError $e) { + restore_error_handler(); // PHP 8+ + $e = $e->getPrevious(); + } + + $this->assertInstanceOf('RuntimeException', $e); + + $now = set_error_handler(function () { }); + restore_error_handler(); + $this->assertEquals($previous, $now); + } + public function signalProvider() { return array( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy