diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 57c3319988..2331b448a6 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -401,6 +401,11 @@ class Process $data = $this->getOutput(); $latest = substr($data, $this->incrementalOutputOffset); + + if (false === $latest) { + return ''; + } + $this->incrementalOutputOffset = strlen($data); return $latest; @@ -442,6 +447,11 @@ class Process $data = $this->getErrorOutput(); $latest = substr($data, $this->incrementalErrorOutputOffset); + + if (false === $latest) { + return ''; + } + $this->incrementalErrorOutputOffset = strlen($data); return $latest; diff --git a/src/Symfony/Component/Process/Tests/AbstractProcessTest.php b/src/Symfony/Component/Process/Tests/AbstractProcessTest.php index 7a4c96c835..1286c107aa 100644 --- a/src/Symfony/Component/Process/Tests/AbstractProcessTest.php +++ b/src/Symfony/Component/Process/Tests/AbstractProcessTest.php @@ -276,6 +276,37 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase unlink($lock); } + public function testGetEmptyIncrementalErrorOutput() + { + // use a lock file to toggle between writing ("W") and reading ("R") the + // output stream + $lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock'); + file_put_contents($lock, 'W'); + + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }'))); + + $p->start(); + + $shouldWrite = false; + + while ($p->isRunning()) { + if ('R' === file_get_contents($lock)) { + if (!$shouldWrite) { + $this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalOutput(), $matches)); + $shouldWrite = true; + } else { + $this->assertSame('', $p->getIncrementalOutput()); + + file_put_contents($lock, 'W'); + $shouldWrite = false; + } + } + usleep(100); + } + + unlink($lock); + } + public function testGetOutput() { $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { echo \' foo \'; $n++; }'))); @@ -305,6 +336,37 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase unlink($lock); } + public function testGetEmptyIncrementalOutput() + { + // use a lock file to toggle between writing ("W") and reading ("R") the + // output stream + $lock = tempnam(sys_get_temp_dir(), get_class($this).'Lock'); + file_put_contents($lock, 'W'); + + $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { if (\'W\' === file_get_contents('.var_export($lock, true).')) { echo \' foo \'; $n++; file_put_contents('.var_export($lock, true).', \'R\'); } usleep(100); }'))); + + $p->start(); + + $shouldWrite = false; + + while ($p->isRunning()) { + if ('R' === file_get_contents($lock)) { + if (!$shouldWrite) { + $this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches)); + $shouldWrite = true; + } else { + $this->assertSame('', $p->getIncrementalOutput()); + + file_put_contents($lock, 'W'); + $shouldWrite = false; + } + } + usleep(100); + } + + unlink($lock); + } + public function testZeroAsOutput() { if ('\\' === DIRECTORY_SEPARATOR) {