8000 merged branch Seldaek/process-win-fix (PR #4400) · symfony/symfony@48ccdaa · GitHub
[go: up one dir, main page]

Skip to content

Commit 48ccdaa

Browse files
committed
merged branch Seldaek/process-win-fix (PR #4400)
Commits ------- bcf8cf9 [Process] Refactor the windows handling so it is always executed 0c5aa8b [Process] Add failing test for callbacks on windows Discussion ---------- [Process] Windows callback handling fix --------------------------------------------------------------------------- by travisbot at 2012-05-24T18:10:56Z This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1424957) (merged bcf8cf9 into e2c36c5).
2 parents 2c50c2d + bcf8cf9 commit 48ccdaa

File tree

2 files changed

+72
-58
lines changed

2 files changed

+72
-58
lines changed

src/Symfony/Component/Process/Process.php

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ public function start($callback = null)
206206
$this->fileHandles = array(
207207
self::STDOUT => tmpfile(),
208208
);
209+
$this->readBytes = array(
210+
self::STDOUT => 0,
211+
);
209212
$descriptors = array(array('pipe', 'r'), $this->fileHandles[self::STDOUT], array('pipe', 'w'));
210213
} else {
211214
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
@@ -236,14 +239,18 @@ public function start($callback = null)
236239
unset($this->pipes[0]);
237240

238241
return;
239-
} else {
240-
$writePipes = array($this->pipes[0]);
241-
unset($this->pipes[0]);
242-
$stdinLen = strlen($this->stdin);
243-
$stdinOffset = 0;
244242
}
245243

244+
$writePipes = array($this->pipes[0]);
245+
unset($this->pipes[0]);
246+
$stdinLen = strlen($this->stdin);
247+
$stdinOffset = 0;
248+
246249
while ($writePipes) {
250+
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
251+
$this->processFileHandles($callback);
252+
}
253+
247254
$r = $this->pipes;
248255
$w = $writePipes;
249256
$e = null;
@@ -252,7 +259,8 @@ public function start($callback = null)
252259

253260
if (false === $n) {
254261
break;
255-
} elseif ($n === 0) {
262+
}
263+
if ($n === 0) {
256264
proc_terminate($this->process);
257265

258266
throw new \RuntimeException('The process timed out.');
@@ -269,22 +277,6 @@ public function start($callback = null)
269277
}
270278
}
271279

272-
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
273-
$fh = $this->fileHandles;
274-
foreach ($fh as $type => $fileHandle) {
275-
fseek($fileHandle, 0);
276-
$data = fread($fileHandle, 8192);
277-
$this->readBytes[$type] = strlen($data);
278-
if (strlen($data) > 0) {
279-
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
280-
}
281-
if (false === $data) {
282-
fclose($fileHandle);
283-
unset($this->fileHandles[$type]);
284-
}
285-
}
286-
}
287-
288280
foreach ($r as $pipe) {
289281
$type = array_search($pipe, $this->pipes);
290282
$data = fread($pipe, 8192);
@@ -319,53 +311,40 @@ public function wait($callback = null)
319311
$this->processInformation = proc_get_status($this->process);
320312
$callback = $this->buildCallback($callback);
321313
while ($this->pipes || (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles)) {
322-
$r = $this->pipes;
323-
$w = null;
324-
$e = null;
314+
if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles) {
315+
$this->processFileHandles($callback, !$this->pipes);
316+
}
325317

326-
$n = @stream_select($r, $w, $e, $this->timeout);
318+
if ($this->pipes) {
319+
$r = $this->pipes;
320+
$w = null;
321+
$e = null;
327322

328-
if (false === $n) {
329-
break;
330-
}
331-
if (0 === $n) {
332-
proc_terminate($this->process);
323+
$n = @stream_select($r, $w, $e, $this->timeout);
333324

334-
throw new \RuntimeException('The process timed out.');
335-
}
325+
if (false === $n) {
326+
$this->pipes = array();
336327

337-
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
338-
$fh = $this->fileHandles;
339-
foreach ($fh as $type => $fileHandle) {
340-
fseek($fileHandle, $this->readBytes[$type]);
341-
$data = fread($fileHandle, 8192);
342-
if (isset($this->readBytes)) {
343-
$this->readBytes[$type] += strlen($data);
344-
} else {
345-
$this->readBytes[$type] = strlen($data);
346-
}
328+
continue;
329+
}
330+
if (0 === $n) {
331+
proc_terminate($this->process);
347332

333+
throw new \RuntimeException('The process timed out.');
334+
}
335+
336+
foreach ($r as $pipe) {
337+
$type = array_search($pipe, $this->pipes);
338+
$data = fread($pipe, 8192);
348339
if (strlen($data) > 0) {
349340
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
350341
}
351-
if (false === $data) {
352-
fclose($fileHandle);
353-
unset($this->fileHandles[$type]);
342+
if (false === $data || feof($pipe)) {
343+
fclose($pipe);
344+
unset($this->pipes[$type]);
354345
}
355346
}
356347
}
357-
358-
foreach ($r as $pipe) {
359-
$type = array_search($pipe, $this->pipes);
360-
$data = fread($pipe, 8192);
361-
if (strlen($data) > 0) {
362-
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
363-
}
364-
if (false === $data || feof($pipe)) {
365-
fclose($pipe);
366-
unset($this->pipes[$type]);
367-
}
368-
}
369348
}
370349
$this->updateStatus();
371350
if ($this->processInformation['signaled']) {
@@ -725,4 +704,27 @@ protected function updateOutput()
725704
$this->addOutput(stream_get_contents($this->pipes[self::STDOUT]));
726705
}
727706
}
707+
708+
/**
709+
* Handles the windows file handles fallbacks
710+
*
711+
* @param mixed $callback A valid PHP callback
712+
* @param Boolean $closeEmptyHandles if true, handles that are empty will be assumed closed
713+
*/
714+
private function processFileHandles($callback, $closeEmptyHandles = false)
715+
{
716+
$fh = $this->fileHandles;
717+
foreach ($fh as $type => $fileHandle) {
718+
fseek($fileHandle, $this->readBytes[$type]);
719+
$data = fread($fileHandle, 8192);
720+
if (strlen($data) > 0) {
721+
$this->readBytes[$type] += strlen($data);
722+
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
723+
}
724+
if (false === $data || ($closeEmptyHandles && '' === $data && feof($fileHandle))) {
725+
fclose($fileHandle);
726+
unset($this->fileHandles[$type]);
727+
}
728+
}
729+
}
728730
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ public function testProcessPipes($expected, $code)
6868
$this->assertSame(0, $p->getExitCode());
6969
}
7070

71+
public function testCallbackIsExecutedForOutput()
72+
{
73+
$p = new Process(sprintf('php -r %s', escapeshellarg('echo \'foo\';')));
74+
75+
$called = false;
76+
$p->run(function ($type, $buffer) use (&$called) {
77+
$called = $buffer === 'foo';
78+
});
79+
80+
$this->assertTrue($called, 'The callback should be executed with the output');
81+
}
82+
7183
public function testExitCodeText()
7284
{
7385
$process = new Process('');

0 commit comments

Comments
 (0)
0