diff --git a/src/ReadableResourceStream.php b/src/ReadableResourceStream.php index bf32450..cfeb5c6 100644 --- a/src/ReadableResourceStream.php +++ b/src/ReadableResourceStream.php @@ -240,7 +240,6 @@ public function isReadable(): bool public function close(): void { if (\is_resource($this->resource) && \get_resource_type($this->resource) === 'stream') { - // Error suppression, as resource might already be closed $meta = \stream_get_meta_data($this->resource); if (\str_contains($meta["mode"], "+")) { @@ -251,6 +250,9 @@ public function close(): void } } + $this->suspension?->resume(); + $this->suspension = null; + $this->free(); } @@ -328,9 +330,6 @@ private function free(): void $this->readable = false; $this->resource = null; - $this->suspension?->resume(); - $this->suspension = null; - EventLoop::cancel($this->callbackId); if (!$this->onClose->isComplete()) { diff --git a/test/ResourceStreamTest.php b/test/ResourceStreamTest.php index 037b4a5..6477cd9 100644 --- a/test/ResourceStreamTest.php +++ b/test/ResourceStreamTest.php @@ -170,6 +170,21 @@ public function testThrowsOnPendingRead(): void async(fn () => $b->read())->await(); } + public function testCloseWithPendingRead(): void + { + /** @noinspection PhpUnusedLocalVariableInspection Required to keep reference */ + [$a, $b] = $this->getStreamPair(); + + $future = async($b->read(...)); + async($b->close(...)); + + self::assertFalse($b->isClosed()); + + self::assertNull($future->await()); + + self::assertTrue($b->isClosed()); + } + public function testResolveSuccessOnClosedStream(): void { [, $b] = $this->getStreamPair();