Skip to content

Commit

Permalink
Merge pull request #58 from clue-labs/fast-exit
Browse files Browse the repository at this point in the history
Detect exit immediately if last process pipe is closed
  • Loading branch information
jsor committed Jan 18, 2018
2 parents 56c7db4 + 3d1e5f7 commit d2b7244
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/Process.php
Expand Up @@ -115,10 +115,18 @@ public function start(LoopInterface $loop, $interval = 0.1)
return;
}

// process already closed => report immediately
if (!$that->isRunning()) {
$that->close();
$that->emit('exit', array($that->getExitCode(), $that->getTermSignal()));
return;
}

// close not detected immediately => check regularly
$loop->addPeriodicTimer($interval, function ($timer) use ($that, $loop) {
if (!$that->isRunning()) {
$that->close();
$loop->cancelTimer($timer);
$that->close();
$that->emit('exit', array($that->getExitCode(), $that->getTermSignal()));
}
});
Expand Down
76 changes: 76 additions & 0 deletions tests/AbstractProcessTest.php
Expand Up @@ -243,6 +243,82 @@ public function testStartAndAllowProcessToExitSuccessfullyUsingEventLoop()
$this->assertFalse($process->isTerminated());
}

public function testProcessWillExitFasterThanExitInterval()
{
$loop = $this->createLoop();
$process = new Process('echo hi');
$process->start($loop, 2);

$time = microtime(true);
$loop->run();
$time = microtime(true) - $time;

$this->assertLessThan(0.1, $time);
}

public function testDetectsClosingStdoutWithoutHavingToWaitForExit()
{
$cmd = 'exec ' . $this->getPhpBinary() . ' -r ' . escapeshellarg('fclose(STDOUT); sleep(1);');

$loop = $this->createLoop();
$process = new Process($cmd);
$process->start($loop);

$closed = false;
$process->stdout->on('close', function () use (&$closed) {
$closed = true;
});

// run loop for 0.1s only
$loop->addTimer(0.1, function () use ($loop) {
$loop->stop();
});
$loop->run();

$this->assertTrue($closed);
}

public function testKeepsRunningEvenWhenAllStdioPipesHaveBeenClosed()
{
$cmd = 'exec ' . $this->getPhpBinary() . ' -r ' . escapeshellarg('fclose(STDIN);fclose(STDOUT);fclose(STDERR);sleep(1);');

$loop = $this->createLoop();
$process = new Process($cmd);
$process->start($loop);

$closed = 0;
$process->stdout->on('close', function () use (&$closed) {
++$closed;
});
$process->stderr->on('close', function () use (&$closed) {
++$closed;
});

// run loop for 0.1s only
$loop->addTimer(0.1, function () use ($loop) {
$loop->stop();
});
$loop->run();

$this->assertEquals(2, $closed);
$this->assertTrue($process->isRunning());
}

public function testDetectsClosingProcessEvenWhenAllStdioPipesHaveBeenClosed()
{
$cmd = 'exec ' . $this->getPhpBinary() . ' -r ' . escapeshellarg('fclose(STDIN);fclose(STDOUT);fclose(STDERR);usleep(10000);');

$loop = $this->createLoop();
$process = new Process($cmd);
$process->start($loop, 0.001);

$time = microtime(true);
$loop->run();
$time = microtime(true) - $time;

$this->assertLessThan(0.1, $time);
}

public function testStartInvalidProcess()
{
$cmd = tempnam(sys_get_temp_dir(), 'react');
Expand Down

0 comments on commit d2b7244

Please sign in to comment.