[Process] Fix stream_select priority when writing to stdin

This commit is contained in:
Nicolas Grekas 2016-03-29 18:06:47 +02:00
parent 2e6982ac67
commit f31e783fd4
4 changed files with 29 additions and 10 deletions

View File

@ -22,10 +22,9 @@ abstract class AbstractPipes implements PipesInterface
public $pipes = array(); public $pipes = array();
/** @var string */ /** @var string */
protected $inputBuffer = ''; private $inputBuffer = '';
/** @var resource|null */ /** @var resource|null */
protected $input; private $input;
/** @var bool */ /** @var bool */
private $blocked = true; private $blocked = true;
@ -91,9 +90,8 @@ abstract class AbstractPipes implements PipesInterface
if (!isset($this->pipes[0])) { if (!isset($this->pipes[0])) {
return; return;
} }
$input = $this->input;
$e = array(); $r = $e = array();
$r = null !== $this->input ? array($this->input) : $e;
$w = array($this->pipes[0]); $w = array($this->pipes[0]);
// let's have a look if something changed in streams // 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 (;;) { for (;;) {
$data = fread($input, self::CHUNK_SIZE); $data = fread($input, self::CHUNK_SIZE);
if (!isset($data[0])) { if (!isset($data[0])) {
@ -124,7 +122,7 @@ abstract class AbstractPipes implements PipesInterface
return array($this->pipes[0]); return array($this->pipes[0]);
} }
} }
if (!isset($data[0]) && feof($input)) { if (feof($input)) {
// no more data to read on input resource // no more data to read on input resource
// use an empty buffer in the next reads // use an empty buffer in the next reads
$this->input = null; $this->input = null;

View File

@ -158,7 +158,7 @@ class Process
$this->setEnv($env); $this->setEnv($env);
} }
$this->input = $input; $this->setInput($input);
$this->setTimeout($timeout); $this->setTimeout($timeout);
$this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
$this->pty = false; $this->pty = false;

View File

@ -80,7 +80,7 @@ class ProcessUtils
* @param string $caller The name of method call that validates the input * @param string $caller The name of method call that validates the input
* @param mixed $input The input to validate * @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 * @throws InvalidArgumentException In case the input is not valid
* *
@ -92,6 +92,9 @@ class ProcessUtils
if (is_resource($input)) { if (is_resource($input)) {
return $input; return $input;
} }
if (is_string($input)) {
return $input;
}
if (is_scalar($input)) { if (is_scalar($input)) {
return (string) $input; return (string) $input;
} }

View File

@ -209,6 +209,24 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expectedLength, strlen($p->getErrorOutput())); $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 * @expectedException \Symfony\Component\Process\Exception\LogicException
* @expectedExceptionMessage Input can not be set while the process is running. * @expectedExceptionMessage Input can not be set while the process is running.