From 3a109a296ce40ed57ce9b524e644df512ac842d8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 3 Apr 2016 17:15:29 +0200 Subject: [PATCH] [Process] Fixes & testNonBlockingNorClearingIteratorOutput --- .../Component/Process/Pipes/UnixPipes.php | 13 ------- .../Component/Process/Pipes/WindowsPipes.php | 15 +------- src/Symfony/Component/Process/Process.php | 20 +++-------- .../Component/Process/Tests/ProcessTest.php | 36 +++++++++++++++++++ 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Component/Process/Pipes/UnixPipes.php b/src/Symfony/Component/Process/Pipes/UnixPipes.php index 8b6cd3f05b44f..273e1735bbeac 100644 --- a/src/Symfony/Component/Process/Pipes/UnixPipes.php +++ b/src/Symfony/Component/Process/Pipes/UnixPipes.php @@ -150,17 +150,4 @@ public function areOpen() { return (bool) $this->pipes; } - - /** - * Creates a new UnixPipes instance. - * - * @param Process $process - * @param string|resource $input - * - * @return UnixPipes - */ - public static function create(Process $process, $input) - { - return new static($process->isTty(), $process->isPty(), $input, !$process->isOutputDisabled() || $process->hasCallback()); - } } diff --git a/src/Symfony/Component/Process/Pipes/WindowsPipes.php b/src/Symfony/Component/Process/Pipes/WindowsPipes.php index 0791171b59e1d..5c8c3b257eb14 100644 --- a/src/Symfony/Component/Process/Pipes/WindowsPipes.php +++ b/src/Symfony/Component/Process/Pipes/WindowsPipes.php @@ -38,7 +38,7 @@ class WindowsPipes extends AbstractPipes /** @var bool */ private $haveReadSupport; - public function __construct($haveReadSupport, $input) + public function __construct($input, $haveReadSupport) { $this->haveReadSupport = (bool) $haveReadSupport; @@ -160,19 +160,6 @@ public function close() $this->fileHandles = array(); } - /** - * Creates a new WindowsPipes instance. - * - * @param Process $process The process - * @param $input - * - * @return WindowsPipes - */ - public static function create(Process $process, $input) - { - return new static(!$process->isOutputDisabled() || $process->hasCallback(), $input); - } - /** * Removes temporary files. */ diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 9e1be7ef0e721..753a880cdbdd2 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -44,6 +44,7 @@ class Process implements \IteratorAggregate const TIMEOUT_PRECISION = 0.2; private $callback; + private $hasCallback = false; private $commandline; private $cwd; private $env; @@ -257,6 +258,7 @@ public function start(callable $callback = null) $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); + $this->hasCallback = null !== $callback; $descriptors = $this->getDescriptors(); $commandline = $this->commandline; @@ -513,7 +515,7 @@ public function getIterator($blocking = true, $clearOutput = true) { $this->readPipesForOutput(__FUNCTION__, false); - while (null !== $this->callback) { + while (null !== $this->callback || !feof($this->stdout) || !feof($this->stderr)) { $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset); if (isset($out[0])) { @@ -1229,18 +1231,6 @@ public static function isPtySupported() return $result = (bool) @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes); } - /** - * Returns whether a callback is used on underlying process output. - * - * @internal - * - * @return bool - */ - public function hasCallback() - { - return (bool) $this->callback; - } - /** * Creates the descriptors needed by the proc_open. * @@ -1252,9 +1242,9 @@ private function getDescriptors() $this->input->rewind(); } if ('\\' === DIRECTORY_SEPARATOR) { - $this->processPipes = WindowsPipes::create($this, $this->input); + $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback); } else { - $this->processPipes = UnixPipes::create($this, $this->input); + $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback); } return $this->processPipes->getDescriptors(); diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 7ccd0415dc2b6..045088b1b6a88 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -1306,6 +1306,42 @@ public function testIteratorOutput() $this->assertSame($expectedOutput, $output); } + public function testNonBlockingNorClearingIteratorOutput() + { + $input = new InputStream(); + + $process = new Process(self::$phpBin.' -r '.escapeshellarg('fwrite(STDOUT, fread(STDIN, 3));')); + $process->setInput($input); + $process->start(); + $output = array(); + + foreach ($process->getIterator(false, false) as $type => $data) { + $output[] = array($type, $data); + break; + } + $expectedOutput = array( + array($process::OUT, ''), + ); + $this->assertSame($expectedOutput, $output); + + $input->write(123); + + foreach ($process->getIterator(false, false) as $type => $data) { + if ('' !== $data) { + $output[] = array($type, $data); + } + } + + $this->assertSame('123', $process->getOutput()); + $this->assertFalse($process->isRunning()); + + $expectedOutput = array( + array($process::OUT, ''), + array($process::OUT, '123'), + ); + $this->assertSame($expectedOutput, $output); + } + /** * @param string $commandline * @param null|string $cwd