fix hanging of unit tests on Windows

This commit is contained in:
Andrej Hudec 2012-04-22 21:52:08 +02:00
parent b9e6bbe21e
commit c2405c0bbc

View File

@ -47,6 +47,9 @@ class Process
private $process;
private $status = self::STATUS_READY;
private $fileHandles;
private $readedBytes;
/**
* Exit codes translation table.
*
@ -195,7 +198,18 @@ class Process
$this->stdout = '';
$this->stderr = '';
$callback = $this->buildCallback($callback);
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
//Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
//Workaround for this problem is to use temporary files instead of pipes on Windows platform.
//@see https://bugs.php.net/bug.php?id=51800
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$this->fileHandles = array(
self::STDOUT => tmpfile(),
);
$descriptors = array(array('pipe', 'r'), $this->fileHandles[self::STDOUT], array('pipe', 'w'));
} else {
$descriptors = array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'w'));
}
$commandline = $this->commandline;
@ -255,6 +269,22 @@ class Process
}
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$fh = $this->fileHandles;
foreach ($fh as $type => $fileHandle) {
fseek($fileHandle, 0);
$data = fread($fileHandle, 8192);
$this->readedBytes[$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);
@ -288,7 +318,7 @@ class Process
{
$this->processInformation = proc_get_status($this->process);
$callback = $this->buildCallback($callback);
while ($this->pipes) {
while ($this->pipes || (defined('PHP_WINDOWS_VERSION_BUILD') && $this->fileHandles)) {
$r = $this->pipes;
$w = null;
$e = null;
@ -304,6 +334,22 @@ class Process
throw new \RuntimeException('The process timed out.');
}
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$fh = $this->fileHandles;
foreach ($fh as $type => $fileHandle) {
fseek($fileHandle, $this->readedBytes[$type]);
$data = fread($fileHandle, 8192);
$this->readedBytes[$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);
@ -517,6 +563,13 @@ class Process
$exitcode = proc_close($this->process);
$this->exitcode = -1 === $this->processInformation['exitcode'] ? $exitcode : $this->processInformation['exitcode'];
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
foreach ($this->fileHandles as $fileHandle) {
fclose($fileHandle);
}
$this->fileHandles = array();
}
}
$this->status = self::STATUS_TERMINATED;
@ -660,7 +713,10 @@ class Process
protected function updateOutput()
{
if (isset($this->pipes[self::STDOUT]) && is_resource($this->pipes[self::STDOUT])) {
if (defined('PHP_WINDOWS_VERSION_BUILD') && isset($this->fileHandles[self::STDOUT]) && is_resource($this->fileHandles[self::STDOUT])) {
fseek($this->fileHandles[self::STDOUT], $this->readedBytes[self::STDOUT]);
$this->addOutput(stream_get_contents($this->fileHandles[self::STDOUT]));
} elseif (isset($this->pipes[self::STDOUT]) && is_resource($this->pipes[self::STDOUT])) {
$this->addOutput(stream_get_contents($this->pipes[self::STDOUT]));
}
}