[Process] Fix potential race condition
This commit is contained in:
parent
e9b8aae787
commit
b114a85609
|
@ -651,8 +651,12 @@ class Process
|
|||
}
|
||||
}
|
||||
|
||||
$this->updateStatus(false);
|
||||
if ($this->processInformation['running']) {
|
||||
if ($this->isRunning()) {
|
||||
if (isset($this->fallbackStatus['pid'])) {
|
||||
unset($this->fallbackStatus['pid']);
|
||||
|
||||
return $this->stop(0, $signal);
|
||||
}
|
||||
$this->close();
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1149,7 @@ class Process
|
|||
*/
|
||||
private function doSignal($signal, $throwException)
|
||||
{
|
||||
if (!$this->isRunning()) {
|
||||
if (null === $pid = $this->getPid()) {
|
||||
if ($throwException) {
|
||||
throw new LogicException('Can not send signal on a non running process.');
|
||||
}
|
||||
|
@ -1154,7 +1158,7 @@ class Process
|
|||
}
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
exec(sprintf('taskkill /F /T /PID %d 2>&1', $this->getPid()), $output, $exitCode);
|
||||
exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
|
||||
if ($exitCode && $this->isRunning()) {
|
||||
if ($throwException) {
|
||||
throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
|
||||
|
@ -1166,8 +1170,8 @@ class Process
|
|||
if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
|
||||
$ok = @proc_terminate($this->process, $signal);
|
||||
} elseif (function_exists('posix_kill')) {
|
||||
$ok = @posix_kill($this->getPid(), $signal);
|
||||
} elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $this->getPid()), array(2 => array('pipe', 'w')), $pipes)) {
|
||||
$ok = @posix_kill($pid, $signal);
|
||||
} elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
|
||||
$ok = false === fgets($pipes[2]);
|
||||
}
|
||||
if (!$ok) {
|
||||
|
|
|
@ -685,22 +685,16 @@ class ProcessTest extends \PHPUnit_Framework_TestCase
|
|||
*/
|
||||
public function testRunProcessWithTimeout()
|
||||
{
|
||||
$timeout = 0.1;
|
||||
$process = $this->getProcess(self::$phpBin.' -r "sleep(1);"');
|
||||
$process->setTimeout($timeout);
|
||||
$process = $this->getProcess(self::$phpBin.' -r "sleep(30);"');
|
||||
$process->setTimeout(0.1);
|
||||
$start = microtime(true);
|
||||
try {
|
||||
$process->run();
|
||||
$this->fail('A RuntimeException should have been raised');
|
||||
} catch (RuntimeException $e) {
|
||||
}
|
||||
$duration = microtime(true) - $start;
|
||||
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
// On Windows, timers are too transient
|
||||
$maxDuration = $timeout + 2 * Process::TIMEOUT_PRECISION;
|
||||
$this->assertLessThan($maxDuration, $duration);
|
||||
}
|
||||
$this->assertLessThan(15, microtime(true) - $start);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
|
Reference in New Issue