From f31e783fd4a44fe7959aa62a1c4e1d2af9aef2bb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 29 Mar 2016 18:06:47 +0200 Subject: [PATCH] [Process] Fix stream_select priority when writing to stdin --- .../Component/Process/Pipes/AbstractPipes.php | 14 ++++++-------- src/Symfony/Component/Process/Process.php | 2 +- src/Symfony/Component/Process/ProcessUtils.php | 5 ++++- .../Component/Process/Tests/ProcessTest.php | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Process/Pipes/AbstractPipes.php b/src/Symfony/Component/Process/Pipes/AbstractPipes.php index f2fd35eb43..ffa6a88319 100644 --- a/src/Symfony/Component/Process/Pipes/AbstractPipes.php +++ b/src/Symfony/Component/Process/Pipes/AbstractPipes.php @@ -22,10 +22,9 @@ abstract class AbstractPipes implements PipesInterface public $pipes = array(); /** @var string */ - protected $inputBuffer = ''; + private $inputBuffer = ''; /** @var resource|null */ - protected $input; - + private $input; /** @var bool */ private $blocked = true; @@ -91,9 +90,8 @@ abstract class AbstractPipes implements PipesInterface if (!isset($this->pipes[0])) { return; } - - $e = array(); - $r = null !== $this->input ? array($this->input) : $e; + $input = $this->input; + $r = $e = array(); $w = array($this->pipes[0]); // let's have a look if something changed in streams @@ -110,7 +108,7 @@ abstract class AbstractPipes implements PipesInterface } } - foreach ($r as $input) { + if ($input) { for (;;) { $data = fread($input, self::CHUNK_SIZE); if (!isset($data[0])) { @@ -124,7 +122,7 @@ abstract class AbstractPipes implements PipesInterface return array($this->pipes[0]); } } - if (!isset($data[0]) && feof($input)) { + if (feof($input)) { // no more data to read on input resource // use an empty buffer in the next reads $this->input = null; diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 8047ef971d..679d33a5e3 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -158,7 +158,7 @@ class Process $this->setEnv($env); } - $this->input = $input; + $this->setInput($input); $this->setTimeout($timeout); $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; $this->pty = false; diff --git a/src/Symfony/Component/Process/ProcessUtils.php b/src/Symfony/Component/Process/ProcessUtils.php index 4f30b630dc..0bd2f6b772 100644 --- a/src/Symfony/Component/Process/ProcessUtils.php +++ b/src/Symfony/Component/Process/ProcessUtils.php @@ -80,7 +80,7 @@ class ProcessUtils * @param string $caller The name of method call that validates the input * @param mixed $input The input to validate * - * @return string The validated input + * @return mixed The validated input * * @throws InvalidArgumentException In case the input is not valid * @@ -92,6 +92,9 @@ class ProcessUtils if (is_resource($input)) { return $input; } + if (is_string($input)) { + return $input; + } if (is_scalar($input)) { return (string) $input; } diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index ae5e971787..2caa5b995e 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -209,6 +209,24 @@ class ProcessTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expectedLength, strlen($p->getErrorOutput())); } + public function testLiveStreamAsInput() + { + $stream = fopen('php://memory', 'r+'); + fwrite($stream, 'hello'); + rewind($stream); + + $p = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'))); + $p->setInput($stream); + $p->start(function ($type, $data) use ($stream) { + if ('hello' === $data) { + fclose($stream); + } + }); + $p->wait(); + + $this->assertSame('hello', $p->getOutput()); + } + /** * @expectedException \Symfony\Component\Process\Exception\LogicException * @expectedExceptionMessage Input can not be set while the process is running.