diff --git a/src/InvalidStreamException.php b/src/InvalidStreamException.php new file mode 100644 index 0000000..0aa70dd --- /dev/null +++ b/src/InvalidStreamException.php @@ -0,0 +1,27 @@ +session = $session; + parent::__construct($message ?? 'Invalid stream resource', $code, $previous); + } + + public function getSession(): IpcSession + { + return $this->session; + } +} diff --git a/src/NativeIpcPeer.php b/src/NativeIpcPeer.php index aa100d0..074b2b8 100644 --- a/src/NativeIpcPeer.php +++ b/src/NativeIpcPeer.php @@ -4,6 +4,8 @@ namespace StreamIpc; use RuntimeException; +use TypeError; +use ValueError; use StreamIpc\Transport\MessageTransport; use StreamIpc\Transport\NativeMessageTransport; @@ -145,9 +147,24 @@ public function tick(?float $timeout = null): void } $writes = $except = null; - if (@stream_select($reads, $writes, $except, $sec, $usec) <= 0) { - // no streams ready or error occurred - return; + try { + if (@stream_select($reads, $writes, $except, $sec, $usec) <= 0) { + // no streams ready or error occurred + return; + } + } catch (TypeError|ValueError $e) { + foreach ($this->readSet as $key => $stream) { + $test = [$stream]; + $w = $ex = null; + try { + stream_select($test, $w, $ex, 0, 0); + } catch (TypeError|ValueError) { + [$session] = $this->fdMap[$key]; + throw new InvalidStreamException($session, null, 0, $e); + } + } + + throw $e; } foreach ($reads as $stream) { diff --git a/tests/Unit/NativeIpcPeerInvalidStreamTest.php b/tests/Unit/NativeIpcPeerInvalidStreamTest.php new file mode 100644 index 0000000..035a140 --- /dev/null +++ b/tests/Unit/NativeIpcPeerInvalidStreamTest.php @@ -0,0 +1,26 @@ +createStreamSession($a, $a, $b); + fclose($b); + + try { + $peer->tick(); + $this->fail('No exception thrown'); + } catch (InvalidStreamException $e) { + $this->assertSame($session, $e->getSession()); + } finally { + fclose($a); + } + } +}