From 3b380bfd9808620b4a38a0dd848b7177de16c734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 13 Aug 2016 18:59:12 +0200 Subject: [PATCH 1/4] Only emit "close" event once for Buffer --- src/Buffer.php | 6 ++++++ tests/BufferTest.php | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Buffer.php b/src/Buffer.php index 1a6c32d..af06734 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -12,6 +12,7 @@ class Buffer extends EventEmitter implements WritableStreamInterface public $listening = false; public $softLimit = 65536; private $writable = true; + private $closed = false; private $loop; private $data = ''; @@ -64,6 +65,11 @@ public function end($data = null) public function close() { + if ($this->closed) { + return; + } + + $this->closed = true; $this->writable = false; $this->listening = false; $this->data = ''; diff --git a/tests/BufferTest.php b/tests/BufferTest.php index 2759d13..03d9eb0 100644 --- a/tests/BufferTest.php +++ b/tests/BufferTest.php @@ -294,6 +294,21 @@ public function testClose() $this->assertFalse($buffer->isWritable()); } + /** + * @covers React\Stream\Buffer::close + */ + public function testDoubleCloseWillEmitOnlyOnce() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + + $buffer = new Buffer($stream, $loop); + $buffer->on('close', $this->expectCallableOnce()); + + $buffer->close(); + $buffer->close(); + } + /** * @covers React\Stream\Buffer::write * @covers React\Stream\Buffer::close From 1e2c01feb94fd95ab7ce5494dd8e3222264589e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Mon, 15 Aug 2016 00:54:41 +0200 Subject: [PATCH 2/4] Close Buffer after emitting "error" event --- src/Buffer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Buffer.php b/src/Buffer.php index af06734..50180d1 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -114,6 +114,7 @@ public function handleWrite() } $this->emit('error', array(new \RuntimeException('Unable to write to stream: ' . $error->getMessage(), 0, $error), $this)); + $this->close(); return; } From 78c5b0f8b23247ebe5908951764e302dc33d2ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Mon, 15 Aug 2016 01:19:26 +0200 Subject: [PATCH 3/4] Remove stream from loop when closing buffer --- src/Buffer.php | 6 +++++- tests/BufferTest.php | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Buffer.php b/src/Buffer.php index 50180d1..8ed56ea 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -69,9 +69,13 @@ public function close() return; } + if ($this->listening) { + $this->listening = false; + $this->loop->removeWriteStream($this->stream); + } + $this->closed = true; $this->writable = false; - $this->listening = false; $this->data = ''; $this->emit('close', array($this)); diff --git a/tests/BufferTest.php b/tests/BufferTest.php index 03d9eb0..04b7768 100644 --- a/tests/BufferTest.php +++ b/tests/BufferTest.php @@ -77,6 +77,20 @@ public function testEmptyWriteDoesNotAddToLoop() $buffer->write(null); } + /** + * @covers React\Stream\Buffer::write + */ + public function testWriteWillAddStreamToLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $buffer = new Buffer($stream, $loop); + + $loop->expects($this->once())->method('addWriteStream')->with($stream); + + $buffer->write('foo'); + } + /** * @covers React\Stream\Buffer::write * @covers React\Stream\Buffer::handleWrite @@ -294,6 +308,35 @@ public function testClose() $this->assertFalse($buffer->isWritable()); } + /** + * @covers React\Stream\Buffer::close + */ + public function testClosingAfterWriteRemovesStreamFromLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $buffer = new Buffer($stream, $loop); + + $loop->expects($this->once())->method('removeWriteStream')->with($stream); + + $buffer->write('foo'); + $buffer->close(); + } + + /** + * @covers React\Stream\Buffer::close + */ + public function testClosingWithoutWritingDoesNotRemoveStreamFromLoop() + { + $stream = fopen('php://temp', 'r+'); + $loop = $this->createLoopMock(); + $buffer = new Buffer($stream, $loop); + + $loop->expects($this->never())->method('removeWriteStream'); + + $buffer->close(); + } + /** * @covers React\Stream\Buffer::close */ From d475b9ec15f9a90ec2ed48ee8023f7dc92908719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 16 Aug 2016 14:08:28 +0200 Subject: [PATCH 4/4] Remove all listeners from Buffer when closing --- src/Buffer.php | 1 + tests/BufferTest.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/Buffer.php b/src/Buffer.php index 8ed56ea..d05a253 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -79,6 +79,7 @@ public function close() $this->data = ''; $this->emit('close', array($this)); + $this->removeAllListeners(); } public function handleWrite() diff --git a/tests/BufferTest.php b/tests/BufferTest.php index 04b7768..8df78c1 100644 --- a/tests/BufferTest.php +++ b/tests/BufferTest.php @@ -306,6 +306,8 @@ public function testClose() $this->assertTrue($buffer->isWritable()); $buffer->close(); $this->assertFalse($buffer->isWritable()); + + $this->assertEquals(array(), $buffer->listeners('close')); } /**