[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:
parent
0c5aa8bf7e
commit
bcf8cf9116
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue