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 d55114e

Browse filesBrowse files
committed
feature #17427 [Process] Allow a callback whenever the output is disabled (romainneutron)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Process] Allow a callback whenever the output is disabled | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | Related to #17390 | License | MIT This was not allowed in the past. However, it's possible with these changes Commits ------- 02f0fc7 [Process] Allow a callback whenever the output is disabled
2 parents 8c51a94 + 02f0fc7 commit d55114e
Copy full SHA for d55114e

File tree

5 files changed

+75
-39
lines changed
Filter options

5 files changed

+75
-39
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Pipes/PipesInterface.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ public function readAndWrite($blocking, $close = false);
5353
*/
5454
public function areOpen();
5555

56+
/**
57+
* Returns if pipes are able to read output.
58+
*
59+
* @return bool
60+
*/
61+
public function haveReadSupport();
62+
5663
/**
5764
* Closes file handles and pipes.
5865
*/

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Pipes/UnixPipes.php
+13-5Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ class UnixPipes extends AbstractPipes
2727
/** @var bool */
2828
private $ptyMode;
2929
/** @var bool */
30-
private $disableOutput;
30+
private $haveReadSupport;
3131

32-
public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
32+
public function __construct($ttyMode, $ptyMode, $input, $haveReadSupport)
3333
{
3434
$this->ttyMode = (bool) $ttyMode;
3535
$this->ptyMode = (bool) $ptyMode;
36-
$this->disableOutput = (bool) $disableOutput;
36+
$this->haveReadSupport = (bool) $haveReadSupport;
3737

3838
if (is_resource($input)) {
3939
$this->input = $input;
@@ -52,7 +52,7 @@ public function __destruct()
5252
*/
5353
public function getDescriptors()
5454
{
55-
if ($this->disableOutput) {
55+
if (!$this->haveReadSupport) {
5656
$nullstream = fopen('/dev/null', 'c');
5757

5858
return array(
@@ -191,6 +191,14 @@ public function readAndWrite($blocking, $close = false)
191191
return $read;
192192
}
193193

194+
/**
195+
* {@inheritdoc}
196+
*/
197+
public function haveReadSupport()
198+
{
199+
return $this->haveReadSupport;
200+
}
201+
194202
/**
195203
* {@inheritdoc}
196204
*/
@@ -209,6 +217,6 @@ public function areOpen()
209217
*/
210218
public static function create(Process $process, $input)
211219
{
212-
return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
220+
return new static($process->isTty(), $process->isPty(), $input, !$process->isOutputDisabled() || $process->hasCallback());
213221
}
214222
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Pipes/WindowsPipes.php
+14-6Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ class WindowsPipes extends AbstractPipes
3636
Process::STDERR => 0,
3737
);
3838
/** @var bool */
39-
private $disableOutput;
39+
private $haveReadSupport;
4040

41-
public function __construct($disableOutput, $input)
41+
public function __construct($haveReadSupport, $input)
4242
{
43-
$this->disableOutput = (bool) $disableOutput;
43+
$this->haveReadSupport = (bool) $haveReadSupport;
4444

45-
if (!$this->disableOutput) {
45+
if ($this->haveReadSupport) {
4646
// Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
4747
// Workaround for this problem is to use temporary files instead of pipes on Windows platform.
4848
//
@@ -76,7 +76,7 @@ public function __destruct()
7676
*/
7777
public function getDescriptors()
7878
{
79-
if ($this->disableOutput) {
79+
if (!$this->haveReadSupport) {
8080
$nullstream = fopen('NUL', 'c');
8181

8282
return array(
@@ -138,6 +138,14 @@ public function readAndWrite($blocking, $close = false)
138138
return $read;
139139
}
140140

141+
/**
142+
* {@inheritdoc}
143+
*/
144+
public function haveReadSupport()
145+
{
146+
return $this->haveReadSupport;
147+
}
148+
141149
/**
142150
* {@inheritdoc}
143151
*/
@@ -168,7 +176,7 @@ public function close()
168176
*/
169177
public static function create(Process $process, $input)
170178
{
171-
return new static($process->isOutputDisabled(), $input);
179+
return new static(!$process->isOutputDisabled() || $process->hasCallback(), $input);
172180
}
173181

174182
/**

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Process.php
+28-5Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,6 @@ public function start(callable $callback = null)
253253
if ($this->isRunning()) {
254254
throw new RuntimeException('Process is already running');
255255
}
256-
if ($this->outputDisabled && null !== $callback) {
257-
throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
258-
}
259256

260257
$this->resetProcessData();
261258
$this->starttime = $this->lastOutputTime = microtime(true);
@@ -353,7 +350,12 @@ public function wait(callable $callback = null)
353350
$this->requireProcessIsStarted(__FUNCTION__);
354351

355352
$this->updateStatus(false);
353+
356354
if (null !== $callback) {
355+
if (!$this->processPipes->haveReadSupport()) {
356+
$this->stop(0);
357+
throw new \LogicException('Pass the callback to the Process:start method or enableOutput to use a callback with Process::wait');
358+
}
357359
$this->callback = $this->buildCallback($callback);
358360
}
359361

@@ -1200,6 +1202,18 @@ public static function isPtySupported()
12001202
return $result = (bool) @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes);
12011203
}
12021204

1205+
/**
1206+
* Returns whether a callback is used on underlying process output.
1207+
*
1208+
* @internal
1209+
*
1210+
* @return bool
1211+
*/
1212+
public function hasCallback()
1213+
{
1214+
return (bool) $this->callback;
1215+
}
1216+
12031217
/**
12041218
* Creates the descriptors needed by the proc_open.
12051219
*
@@ -1226,10 +1240,19 @@ private function getDescriptors()
12261240
*
12271241
* @return \Closure A PHP closure
12281242
*/
1229-
protected function buildCallback($callback)
1243+
protected function buildCallback(callable $callback = null)
12301244
{
1245+
if ($this->outputDisabled) {
1246+
return function ($type, $data) use ($callback) {
1247+
if (null !== $callback) {
1248+
call_user_func($callback, $type, $data);
1249+
}
1250+
};
1251+
}
1252+
12311253
$out = self::OUT;
1232-
$callback = function ($type, $data) use ($callback, $out) {
1254+
1255+
return function ($type, $data) use ($callback, $out) {
12331256
if ($out == $type) {
12341257
$this->addOutput($data);
12351258
} else {

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Process/Tests/ProcessTest.php
+13-23Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,19 @@ public function testCallbackIsExecutedForOutput()
305305
$this->assertTrue($called, 'The callback should be executed with the output');
306306
}
307307

308+
public function testCallbackIsExecutedForOutputWheneverOutputIsDisabled()
309+
{
310+
$p = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('echo \'foo\';')));
311+
$p->disableOutput();
312+
313+
$called = false;
314+
$p->run(function ($type, $buffer) use (&$called) {
315+
$called = $buffer === 'foo';
316+
});
317+
318+
$this->assertTrue($called, 'The callback should be executed with the output');
319+
}
320+
308321
public function testGetErrorOutput()
309322
{
310323
$p = $this->getProcess(sprintf('%s -r %s', self::$phpBin, escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));
@@ -1108,29 +1121,6 @@ public function testSetNullIdleTimeoutWhileOutputIsDisabled()
11081121
$this->assertSame($process, $process->setIdleTimeout(null));
11091122
}
11101123

1111-
/**
1112-
* @dataProvider provideStartMethods
1113-
*/
1114-
public function testStartWithACallbackAndDisabledOutput($startMethod, $exception, $exceptionMessage)
1115-
{
1116-
$p = $this->getProcess('foo');
1117-
$p->disableOutput();
1118-
$this->setExpectedException($exception, $exceptionMessage);
1119-
if ('mustRun' === $startMethod) {
1120-
$this->skipIfNotEnhancedSigchild();
1121-
}
1122-
$p->{$startMethod}(function () {});
1123-
}
1124-
1125-
public function provideStartMethods()
1126-
{
1127-
return array(
1128-
array('start', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
1129-
array('run', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
1130-
array('mustRun', 'Symfony\Component\Process\Exception\LogicException', 'Output has been disabled, enable it to allow the use of a callback.'),
1131-
);
1132-
}
1133-
11341124
/**
11351125
* @dataProvider provideOutputFetchingMethods
11361126
* @expectedException \Symfony\Component\Process\Exception\LogicException

0 commit comments

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