diff --git a/.travis.yml b/.travis.yml index 985aad4..ff82bf2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,8 @@ php: - 5.4 - 5.5 - 5.6 + - 7.0 - hhvm - - hhvm-nightly - -matrix: - allow_failures: - - php: hhvm-nightly before_script: - composer install --dev --prefer-source diff --git a/composer.json b/composer.json index ed6521e..145e914 100644 --- a/composer.json +++ b/composer.json @@ -14,10 +14,5 @@ }, "autoload": { "psr-4": { "React\\ChildProcess\\": "src" } - }, - "extra": { - "branch-alias": { - "dev-master": "0.5-dev" - } } } diff --git a/src/Process.php b/src/Process.php index 48f2b1f..5fd28c1 100644 --- a/src/Process.php +++ b/src/Process.php @@ -4,7 +4,7 @@ use Evenement\EventEmitter; use React\EventLoop\LoopInterface; -use React\EventLoop\Timer\Timer; +use React\EventLoop\Timer\TimerInterface; use React\Stream\Stream; /** @@ -101,18 +101,31 @@ public function start(LoopInterface $loop, $interval = 0.1) throw new \RuntimeException('Unable to launch a new process.'); } + $closeCount = 0; + + $streamCloseHandler = function (Stream $stream) use (&$closeCount, $loop, $interval) { + $closeCount++; + + if ($closeCount < 2) { + return; + } + + $loop->addPeriodicTimer($interval, function (TimerInterface $timer) { + if (!$this->isRunning()) { + $this->close(); + $timer->cancel(); + $this->emit('exit', array($this->getExitCode(), $this->getTermSignal())); + } + }); + + }; + $this->stdin = new Stream($this->pipes[0], $loop); $this->stdin->pause(); $this->stdout = new Stream($this->pipes[1], $loop); + $this->stdout->on('close', $streamCloseHandler); $this->stderr = new Stream($this->pipes[2], $loop); - - $loop->addPeriodicTimer($interval, function (Timer $timer) { - if (!$this->isRunning()) { - $this->close(); - $timer->cancel(); - $this->emit('exit', array($this->getExitCode(), $this->getTermSignal())); - } - }); + $this->stderr->on('close', $streamCloseHandler); } /** diff --git a/tests/AbstractProcessTest.php b/tests/AbstractProcessTest.php index c11c63a..1cea3cf 100644 --- a/tests/AbstractProcessTest.php +++ b/tests/AbstractProcessTest.php @@ -298,6 +298,46 @@ public function testTerminateWithStopAndContinueSignalsUsingEventLoop() $this->assertFalse($process->isTerminated()); } + public function testIssue18() { + $loop = $this->createLoop(); + + $testString = 'x'; + + $process = new Process($this->getPhpBinary() . " -r 'echo \"$testString\";'"); + + $stdOut = ''; + $stdErr = ''; + + $process->on( + 'exit', + function ($exitCode) use (&$stdOut, &$stdErr, $testString) { + $this->assertEquals(0, $exitCode, "Exit code is 0"); + + $this->assertEquals($testString, $stdOut); + } + ); + + $process->start($loop); + + $process->stdout->on( + 'data', + function ($output) use (&$stdOut) { + $stdOut .= $output; + } + ); + $process->stderr->on( + 'data', + function ($output) use (&$stdErr) { + $stdErr .= $output; + } + ); + + $loop->tick(); + sleep(1); // comment this line out and it works fine + + $loop->run(); + } + /** * Execute a callback at regular intervals until it returns successfully or * a timeout is reached.