Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 02f0fc7

Browse files
committed
[Process] Allow a callback whenever the output is disabled
1 parent caae21c commit 02f0fc7

File tree

5 files changed

+76
-40
lines changed

5 files changed

+76
-40
lines changed

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

Lines 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

Lines 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

Lines 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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,6 @@ public function start(callable $callback = null)
256256
if ($this->isRunning()) {
257257
throw new RuntimeException('Process is already running');
258258
}
259-
if ($this->outputDisabled && null !== $callback) {
260-
throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
261-
}
262259

263260
$this->resetProcessData();
264261
$this->starttime = $this->lastOutputTime = microtime(true);
@@ -356,7 +353,12 @@ public function wait(callable $callback = null)
356353
$this->requireProcessIsStarted(__FUNCTION__);
357354

358355
$this->updateStatus(false);
356+
359357
if (null !== $callback) {
358+
if (!$this->processPipes->haveReadSupport()) {
359+
$this->stop(0);
360+
throw new \LogicException('Pass the callback to the Process:start method or enableOutput to use a callback with Process::wait');
361+
}
360362
$this->callback = $this->buildCallback($callback);
361363
}
362364

@@ -1181,6 +1183,18 @@ public static function isPtySupported()
11811183
return $result = (bool) @proc_open('echo 1', array(array('pty'), array('pty'), array('pty')), $pipes);
11821184
}
11831185

1186+
/**
1187+
* Returns whether a callback is used on underlying process output.
1188+
*
1189+
* @internal
1190+
*
1191+
* @return bool
1192+
*/
1193+
public function hasCallback()
1194+
{
1195+
return (bool) $this->callback;
1196+
}
1197+
11841198
/**
11851199
* Creates the descriptors needed by the proc_open.
11861200
*
@@ -1194,7 +1208,7 @@ private function getDescriptors()
11941208
$this->processPipes = UnixPipes::create($this, $this->input);
11951209
}
11961210

1197-
return $this->processPipes->getDescriptors($this->outputDisabled);
1211+
return $this->processPipes->getDescriptors();
11981212
}
11991213

12001214
/**
@@ -1207,10 +1221,19 @@ private function getDescriptors()
12071221
*
12081222
* @return \Closure A PHP closure
12091223
*/
1210-
protected function buildCallback($callback)
1224+
protected function buildCallback(callable $callback = null)
12111225
{
1226+
if ($this->outputDisabled) {
1227+
return function ($type, $data) use ($callback) {
1228+
if (null !== $callback) {
1229+
call_user_func($callback, $type, $data);
1230+
}
1231+
};
1232+
}
1233+
12121234
$out = self::OUT;
1213-
$callback = function ($type, $data) use ($callback, $out) {
1235+
1236+
return function ($type, $data) use ($callback, $out) {
12141237
if ($out == $type) {
12151238
$this->addOutput($data);
12161239
} else {

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

Lines 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)