From bd859b2ca975d047e0bfe2a7ef72f208a0c26715 Mon Sep 17 00:00:00 2001 From: Bogdan Lysenko Date: Thu, 2 Jul 2015 01:43:49 +0300 Subject: [PATCH 1/3] Prevent infinite loop on connection close --- src/Buffer.php | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Buffer.php b/src/Buffer.php index 18211ea..78b1bee 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -14,17 +14,13 @@ class Buffer extends EventEmitter implements WritableStreamInterface private $writable = true; private $loop; private $data = ''; - private $lastError = array( - 'number' => 0, - 'message' => '', - 'file' => '', - 'line' => 0, - ); + private $lastError; public function __construct($stream, LoopInterface $loop) { $this->stream = $stream; $this->loop = $loop; + $this->lastErrorFlush(); } public function isWritable() @@ -83,13 +79,15 @@ public function handleWrite() return; } + $this->lastErrorFlush(); + set_error_handler(array($this, 'errorHandler')); $sent = fwrite($this->stream, $this->data); restore_error_handler(); - if (false === $sent) { + if (false === $sent || ($sent === 0 && strpos($this->lastError['message'], 'errno=10054') !== false)) { $this->emit('error', array( new \ErrorException( $this->lastError['message'], @@ -132,4 +130,13 @@ private function errorHandler($errno, $errstr, $errfile, $errline) $this->lastError['file'] = $errfile; $this->lastError['line'] = $errline; } + + private function lastErrorFlush() { + $this->lastError = [ + 'number' => 0, + 'message' => '', + 'file' => '', + 'line' => 0, + ]; + } } From b977925e48fc009d9bf17627e341e20ccf6c7df9 Mon Sep 17 00:00:00 2001 From: Bohdan Lysenko Date: Mon, 2 Nov 2015 01:17:47 +0200 Subject: [PATCH 2/3] Prevent infinite loop on connection close --- src/Buffer.php | 7 +++---- tests/BufferTest.php | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Buffer.php b/src/Buffer.php index 78b1bee..df822ae 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -87,7 +87,7 @@ public function handleWrite() restore_error_handler(); - if (false === $sent || ($sent === 0 && strpos($this->lastError['message'], 'errno=10054') !== false)) { + if ($this->lastError['number'] > 0) { $this->emit('error', array( new \ErrorException( $this->lastError['message'], @@ -102,9 +102,8 @@ public function handleWrite() return; } - if (0 === $sent && feof($this->stream)) { - $this->emit('error', array(new \RuntimeException('Tried to write to closed stream.'), $this)); - + if ($sent === false) { + $this->emit('error', array(new \RuntimeException('Send failed'), $this)); return; } diff --git a/tests/BufferTest.php b/tests/BufferTest.php index 1fc4d1e..cf6a131 100644 --- a/tests/BufferTest.php +++ b/tests/BufferTest.php @@ -208,7 +208,7 @@ public function testWritingToClosedStream() $buffer->write('bar'); $this->assertInstanceOf('Exception', $error); - $this->assertSame('Tried to write to closed stream.', $error->getMessage()); + $this->assertSame('fwrite(): send of 3 bytes failed with errno=32 Broken pipe', $error->getMessage()); } private function createWriteableLoopMock() From 5ee8289a8e39cd2b5bf78e4a458b43d63c0a2359 Mon Sep 17 00:00:00 2001 From: Bohdan Lysenko Date: Mon, 2 Nov 2015 01:30:37 +0200 Subject: [PATCH 3/3] change array definition (for php 5.3 compatibility) --- src/Buffer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Buffer.php b/src/Buffer.php index df822ae..6f83bef 100644 --- a/src/Buffer.php +++ b/src/Buffer.php @@ -131,11 +131,11 @@ private function errorHandler($errno, $errstr, $errfile, $errline) } private function lastErrorFlush() { - $this->lastError = [ + $this->lastError = array( 'number' => 0, 'message' => '', 'file' => '', 'line' => 0, - ]; + ); } }