Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 428f12e

Browse filesBrowse files
[Process] Turn getIterator() args to flags & add ITER_SKIP_OUT/ERR modes
1 parent f1d12a1 commit 428f12e
Copy full SHA for 428f12e

File tree

Expand file treeCollapse file tree

3 files changed

+61
-30
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+61
-30
lines changed

‎src/Symfony/Component/Process/Process.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Process.php
+33-20Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ class Process implements \IteratorAggregate
4343
// Timeout Precision in seconds.
4444
const TIMEOUT_PRECISION = 0.2;
4545

46+
const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
47+
const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory
48+
const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating
49+
const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating
50+
4651
private $callback;
4752
private $hasCallback = false;
4853
private $commandline;
@@ -503,41 +508,49 @@ public function getIncrementalOutput()
503508
/**
504509
* Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).
505510
*
506-
* @param bool $blocking Whether to use a blocking read call.
507-
* @param bool $clearOutput Whether to clear or keep output in memory.
511+
* @param int $flags A bit field of Process::ITER_* flags.
508512
*
509513
* @throws LogicException in case the output has been disabled
510514
* @throws LogicException In case the process is not started
511515
*
512516
* @return \Generator
513517
*/
514-
public function getIterator($blocking = true, $clearOutput = true)
518+
public function getIterator($flags = 0)
515519
{
516520
$this->readPipesForOutput(__FUNCTION__, false);
517521

518-
while (null !== $this->callback || !feof($this->stdout) || !feof($this->stderr)) {
519-
$out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
522+
$clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);
523+
$blocking = !(self::ITER_NON_BLOCKING & $flags);
524+
$yieldOut = !(self::ITER_SKIP_OUT & $flags);
525+
$yieldErr = !(self::ITER_SKIP_ERR & $flags);
520526

521-
if (isset($out[0])) {
522-
if ($clearOutput) {
523-
$this->clearOutput();
524-
} else {
525-
$this->incrementalOutputOffset = ftell($this->stdout);
526-
}
527+
while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) {
528+
if ($yieldOut) {
529+
$out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
530+
531+
if (isset($out[0])) {
532+
if ($clearOutput) {
533+
$this->clearOutput();
534+
} else {
535+
$this->incrementalOutputOffset = ftell($this->stdout);
536+
}
527537

528-
yield self::OUT => $out;
538+
yield self::OUT => $out;
539+
}
529540
}
530541

531-
$err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
542+
if ($yieldErr) {
543+
$err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
532544

533-
if (isset($err[0])) {
534-
if ($clearOutput) {
535-
$this->clearErrorOutput();
536-
} else {
537-
$this->incrementalErrorOutputOffset = ftell($this->stderr);
538-
}
545+
if (isset($err[0])) {
546+
if ($clearOutput) {
547+
$this->clearErrorOutput();
548+
} else {
549+
$this->incrementalErrorOutputOffset = ftell($this->stderr);
550+
}
539551

540-
yield self::ERR => $err;
552+
yield self::ERR => $err;
553+
}
541554
}
542555

543556
if (!$blocking && !isset($out[0]) && !isset($err[0])) {

‎src/Symfony/Component/Process/ProcessUtils.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/ProcessUtils.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ public static function validateInput($caller, $input)
9696
if (is_scalar($input)) {
9797
return (string) $input;
9898
}
99+
if ($input instanceof Process) {
100+
return $input->getIterator($input::ITER_SKIP_ERR);
101+
}
99102
if ($input instanceof \Iterator) {
100103
return $input;
101104
}

‎src/Symfony/Component/Process/Tests/ProcessTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Tests/ProcessTest.php
+25-10Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ public function pipesCodeProvider()
11541154
* @dataProvider provideVariousIncrementals
11551155
*/
11561156
public function testIncrementalOutputDoesNotRequireAnotherCall($stream, $method) {
1157-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\''.$stream.'\', $n, 1); $n++; usleep(1000); }'), null, null, null, null);
1157+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\''.$stream.'\', $n, 1); $n++; usleep(1000); }'), null, null, null, null);
11581158
$process->start();
11591159
$result = '';
11601160
$limit = microtime(true) + 3;
@@ -1182,7 +1182,7 @@ public function testIteratorInput()
11821182
yield 'pong';
11831183
};
11841184

1185-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'), null, null, $input());
1185+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'), null, null, $input());
11861186
$process->run();
11871187
$this->assertSame('pingpong', $process->getOutput());
11881188
}
@@ -1191,7 +1191,7 @@ public function testSimpleInputStream()
11911191
{
11921192
$input = new InputStream();
11931193

1194-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('echo \'ping\'; stream_copy_to_stream(STDIN, STDOUT);'));
1194+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('echo \'ping\'; stream_copy_to_stream(STDIN, STDOUT);'));
11951195
$process->setInput($input);
11961196

11971197
$process->start(function ($type, $data) use ($input) {
@@ -1225,7 +1225,7 @@ public function testInputStreamWithCallable()
12251225
$input->onEmpty($stream);
12261226
$input->write($stream());
12271227

1228-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'));
1228+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('echo fread(STDIN, 3);'));
12291229
$process->setInput($input);
12301230
$process->start(function ($type, $data) use ($input) {
12311231
$input->close();
@@ -1243,7 +1243,7 @@ public function testInputStreamWithGenerator()
12431243
$input->close();
12441244
});
12451245

1246-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'));
1246+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);'));
12471247
$process->setInput($input);
12481248
$process->start();
12491249
$input->write('ping');
@@ -1257,7 +1257,7 @@ public function testInputStreamOnEmpty()
12571257
$input = new InputStream();
12581258
$input->onEmpty(function () use (&$i) {++$i;});
12591259

1260-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('echo 123; echo fread(STDIN, 1); echo 456;'));
1260+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('echo 123; echo fread(STDIN, 1); echo 456;'));
12611261
$process->setInput($input);
12621262
$process->start(function ($type, $data) use ($input) {
12631263
if ('123' === $data) {
@@ -1274,7 +1274,7 @@ public function testIteratorOutput()
12741274
{
12751275
$input = new InputStream();
12761276

1277-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('fwrite(STDOUT, 123); fwrite(STDERR, 234); fwrite(STDOUT, fread(STDIN, 3)); fwrite(STDERR, 456);'));
1277+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('fwrite(STDOUT, 123); fwrite(STDERR, 234); flush(); usleep(10000); fwrite(STDOUT, fread(STDIN, 3)); fwrite(STDERR, 456);'));
12781278
$process->setInput($input);
12791279
$process->start();
12801280
$output = array();
@@ -1310,12 +1310,12 @@ public function testNonBlockingNorClearingIteratorOutput()
13101310
{
13111311
$input = new InputStream();
13121312

1313-
$process = new Process(self::$phpBin.' -r '.escapeshellarg('fwrite(STDOUT, fread(STDIN, 3));'));
1313+
$process = $this->getProcess(self::$phpBin.' -r '.escapeshellarg('fwrite(STDOUT, fread(STDIN, 3));'));
13141314
$process->setInput($input);
13151315
$process->start();
13161316
$output = array();
13171317

1318-
foreach ($process->getIterator(false, false) as $type => $data) {
1318+
foreach ($process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type => $data) {
13191319
$output[] = array($type, $data);
13201320
break;
13211321
}
@@ -1326,7 +1326,7 @@ public function testNonBlockingNorClearingIteratorOutput()
13261326

13271327
$input->write(123);
13281328

1329-
foreach ($process->getIterator(false, false) as $type => $data) {
1329+
foreach ($process->getIterator($process::ITER_NON_BLOCKING | $process::ITER_KEEP_OUTPUT) as $type => $data) {
13301330
if ('' !== $data) {
13311331
$output[] = array($type, $data);
13321332
}
@@ -1342,6 +1342,21 @@ public function testNonBlockingNorClearingIteratorOutput()
13421342
$this->assertSame($expectedOutput, $output);
13431343
}
13441344

1345+
public function testChainedProcesses()
1346+
{
1347+
$p1 = new Process(self::$phpBin.' -r '.escapeshellarg('fwrite(STDERR, 123); fwrite(STDOUT, 456);'));
1348+
$p2 = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('stream_copy_to_stream(STDIN, STDOUT);')));
1349+
$p2->setInput($p1);
1350+
1351+
$p1->start();
1352+
$p2->run();
1353+
1354+
$this->assertSame('123', $p1->getErrorOutput());
1355+
$this->assertSame('', $p1->getOutput());
1356+
$this->assertSame('', $p2->getErrorOutput());
1357+
$this->assertSame('456', $p2->getOutput());
1358+
}
1359+
13451360
/**
13461361
* @param string $commandline
13471362
* @param null|string $cwd

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.