Skip to content

Commit

Permalink
Merge pull request #123 from clue-labs/refcount
Browse files Browse the repository at this point in the history
Fix ExtEventLoop to keep track of stream resources (refcount)
  • Loading branch information
jsor authored Dec 1, 2017
2 parents 61e3e65 + 4dd1532 commit 7bc0172
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/ExtEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ExtEventLoop implements LoopInterface
private $streamCallback;
private $streamEvents = [];
private $streamFlags = [];
private $streamRefs = [];
private $readListeners = [];
private $writeListeners = [];
private $running;
Expand Down Expand Up @@ -110,7 +111,8 @@ private function removeStream($stream)
$this->streamFlags[$key],
$this->streamEvents[$key],
$this->readListeners[$key],
$this->writeListeners[$key]
$this->writeListeners[$key],
$this->streamRefs[$key]
);
}
}
Expand Down Expand Up @@ -224,6 +226,12 @@ private function subscribeStreamEvent($stream, $flag)

$this->streamEvents[$key] = $event;
$this->streamFlags[$key] = $flag;

// ext-event does not increase refcount on stream resources for PHP 7+
// manually keep track of stream resource to prevent premature garbage collection
if (PHP_VERSION_ID >= 70000) {
$this->streamRefs[$key] = $stream;
}
}

$event->add();
Expand Down
33 changes: 33 additions & 0 deletions tests/AbstractLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,39 @@ public function testAddReadStreamIgnoresSecondCallable()
$this->tickLoop($this->loop);
}

public function testAddReadStreamReceivesDataFromStreamReference()
{
$this->received = '';
$this->subAddReadStreamReceivesDataFromStreamReference();
$this->assertEquals('', $this->received);

$this->assertRunFasterThan($this->tickTimeout * 2);
$this->assertEquals('[hello]X', $this->received);
}

/**
* Telper for above test. This happens in another helper method to verify
* the loop keep track of assigned stream resources (refcount).
*/
private function subAddReadStreamReceivesDataFromStreamReference()
{
list ($input, $output) = $this->createSocketPair();

fwrite($input, 'hello');
fclose($input);

$this->loop->addReadStream($output, function ($output) {
$chunk = fread($output, 1024);
if ($chunk === '') {
$this->received .= 'X';
$this->loop->removeReadStream($output);
fclose($output);
} else {
$this->received .= '[' . $chunk . ']';
}
});
}

public function testAddWriteStream()
{
list ($input) = $this->createSocketPair();
Expand Down

0 comments on commit 7bc0172

Please sign in to comment.