[Process] Refactor the windows handling so it is always executed

When regular pipes are closed, the file handlers fallback on windows
should still be processed until they are empty
This commit is contained in:
Jordi Boggiano 2012-05-24 19:53:48 +02:00
parent 0c5aa8bf7e
commit bcf8cf9116
1 changed files with 62 additions and 60 deletions

View File

@ -206,6 +206,9 @@ class Process
$this->fileHandles = array(
self::STDOUT => tmpfile(),
);
$this->readBytes = array(
self::STDOUT => 0,
);
$descriptors = array(array('pipe', 'r'), $this->fileHandles[self::STDOUT], array('pipe', 'w'));
} else {
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
@ -236,14 +239,18 @@ class Process
unset($this->pipes[0]);
return;
} else {
$writePipes = array($this->pipes[0]);
unset($this->pipes[0]);
$stdinLen = strlen($this->stdin);
$stdinOffset = 0;
}
$writePipes = array($this->pipes[0]);
unset($this->pipes[0]);
$stdinLen = strlen($this->stdin);
$stdinOffset = 0;
while ($writePipes) {
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$this->processFileHandles($callback);
}
$r = $this->pipes;
$w = $writePipes;
$e = null;
@ -252,7 +259,8 @@ class Process
if (false === $n) {
break;
} elseif ($n === 0) {
}
if ($n === 0) {
proc_terminate($this->process);
throw new \RuntimeException('The process timed out.');
@ -269,22 +277,6 @@ class Process
}
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$fh = $this->fileHandles;
foreach ($fh as $type => $fileHandle) {
fseek($fileHandle, 0);
$data = fread($fileHandle, 8192);
$this->readBytes[$type] = strlen($data);
if (strlen($data) > 0) {
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
}
if (false === $data) {
fclose($fileHandle);
unset($this->fileHandles[$type]);
}
}
}
foreach ($r as $pipe) {
$type = array_search($pipe, $this->pipes);
$data = fread($pipe, 8192);
@ -319,53 +311,40 @@ class Process
$this->processInformation = proc_get_status($this->process);
$callback = $this->buildCallback($callback);
while ($this->pipes || (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles)) {
$r = $this->pipes;
$w = null;
$e = null;
$n = @stream_select($r, $w, $e, $this->timeout);
if (false === $n) {
break;
}
if (0 === $n) {
proc_terminate($this->process);
throw new \RuntimeException('The process timed out.');
if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles) {
$this->processFileHandles($callback, !$this->pipes);
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$fh = $this->fileHandles;
foreach ($fh as $type => $fileHandle) {
fseek($fileHandle, $this->readBytes[$type]);
$data = fread($fileHandle, 8192);
if (isset($this->readBytes)) {
$this->readBytes[$type] += strlen($data);
} else {
$this->readBytes[$type] = strlen($data);
}
if ($this->pipes) {
$r = $this->pipes;
$w = null;
$e = null;
$n = @stream_select($r, $w, $e, $this->timeout);
if (false === $n) {
$this->pipes = array();
continue;
}
if (0 === $n) {
proc_terminate($this->process);
throw new \RuntimeException('The process timed out.');
}
foreach ($r as $pipe) {
$type = array_search($pipe, $this->pipes);
$data = fread($pipe, 8192);
if (strlen($data) > 0) {
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
}
if (false === $data) {
fclose($fileHandle);
unset($this->fileHandles[$type]);
if (false === $data || feof($pipe)) {
fclose($pipe);
unset($this->pipes[$type]);
}
}
}
foreach ($r as $pipe) {
$type = array_search($pipe, $this->pipes);
$data = fread($pipe, 8192);
if (strlen($data) > 0) {
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
}
if (false === $data || feof($pipe)) {
fclose($pipe);
unset($this->pipes[$type]);
}
}
}
$this->updateStatus();
if ($this->processInformation['signaled']) {
@ -725,4 +704,27 @@ class Process
$this->addOutput(stream_get_contents($this->pipes[self::STDOUT]));
}
}
/**
* Handles the windows file handles fallbacks
*
* @param mixed $callback A valid PHP callback
* @param Boolean $closeEmptyHandles if true, handles that are empty will be assumed closed
*/
private function processFileHandles($callback, $closeEmptyHandles = false)
{
$fh = $this->fileHandles;
foreach ($fh as $type => $fileHandle) {
fseek($fileHandle, $this->readBytes[$type]);
$data = fread($fileHandle, 8192);
if (strlen($data) > 0) {
$this->readBytes[$type] += strlen($data);
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
}
if (false === $data || ($closeEmptyHandles && '' === $data && feof($fileHandle))) {
fclose($fileHandle);
unset($this->fileHandles[$type]);
}
}
}
}