Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fd64996

Browse files
committed
[Stream] Fix infinite loop writing to closed stream
1 parent 0dac387 commit fd64996

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

src/React/Stream/Buffer.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use Evenement\EventEmitter;
66
use React\EventLoop\LoopInterface;
7-
use React\Stream\WritableStreamInterface;
87

98
/** @event full-drain */
109
class Buffer extends EventEmitter implements WritableStreamInterface
@@ -83,8 +82,8 @@ public function close()
8382

8483
public function handleWrite()
8584
{
86-
if (!is_resource($this->stream) || ('generic_socket' === $this->meta['stream_type'] && feof($this->stream))) {
87-
$this->emit('error', array(new \RuntimeException('Tried to write to closed or invalid stream.')));
85+
if (!is_resource($this->stream)) {
86+
$this->emit('error', array(new \RuntimeException('Tried to write to invalid stream.'), $this));
8887

8988
return;
9089
}
@@ -107,6 +106,12 @@ public function handleWrite()
107106
return;
108107
}
109108

109+
if (0 === $sent && feof($this->stream)) {
110+
$this->emit('error', array(new \RuntimeException('Tried to write to closed stream.'), $this));
111+
112+
return;
113+
}
114+
110115
$len = strlen($this->data);
111116
if ($len >= $this->softLimit && $len - $sent < $this->softLimit) {
112117
$this->emit('drain');

tests/React/Tests/Stream/BufferTest.php

+22-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,28 @@ public function testError()
184184

185185
$buffer->write('Attempting to write to bad stream');
186186
$this->assertInstanceOf('Exception', $error);
187-
$this->assertSame('Tried to write to closed or invalid stream.', $error->getMessage());
187+
$this->assertSame('Tried to write to invalid stream.', $error->getMessage());
188+
}
189+
190+
public function testWritingToClosedStream()
191+
{
192+
list($a, $b) = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
193+
$loop = $this->createWriteableLoopMock();
194+
195+
$error = null;
196+
197+
$buffer = new Buffer($a, $loop);
198+
$buffer->on('error', function($message) use (&$error) {
199+
$error = $message;
200+
});
201+
202+
$buffer->write('foo');
203+
stream_socket_shutdown($b, STREAM_SHUT_RD);
204+
stream_socket_shutdown($a, STREAM_SHUT_RD);
205+
$buffer->write('bar');
206+
207+
$this->assertInstanceOf('Exception', $error);
208+
$this->assertSame('Tried to write to closed stream.', $error->getMessage());
188209
}
189210

190211
private function createWriteableLoopMock()

0 commit comments

Comments
 (0)