merged branch romainneutron/process-timeout (PR #7580)
This PR was merged into the 2.1 branch.
Discussion
----------
[2.1][Process] Fix timeout in Process::stop method
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #7579
| License | MIT
- The timeout is ten times more than set.
- The timeout does not occurs, it is actually blocking until the process dies.
Commits
-------
bec8ff1
Fix timeout in Process::stop method
This commit is contained in:
commit
ebbb96ee46
@ -601,7 +601,7 @@ class Process
|
||||
*/
|
||||
public function stop($timeout=10)
|
||||
{
|
||||
$timeoutMicro = (int) $timeout*10E6;
|
||||
$timeoutMicro = (int) $timeout*1E6;
|
||||
if ($this->isRunning()) {
|
||||
proc_terminate($this->process);
|
||||
$time = 0;
|
||||
@ -610,6 +610,10 @@ class Process
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
if (!defined('PHP_WINDOWS_VERSION_BUILD') && $this->isRunning()) {
|
||||
proc_terminate($this->process, SIGKILL);
|
||||
}
|
||||
|
||||
foreach ($this->pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
|
@ -45,6 +45,31 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertNull($p->getTimeout());
|
||||
}
|
||||
|
||||
public function testStopWithTimeoutIsActuallyWorking()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
$this->markTestSkipped('Stop with timeout does not work on windows, it requires posix signals');
|
||||
}
|
||||
if (!function_exists('pcntl_signal')) {
|
||||
$this->markTestSkipped('This test require pcntl_signal function');
|
||||
}
|
||||
|
||||
// exec is mandatory here since we send a signal to the process
|
||||
// see https://github.com/symfony/symfony/issues/5030 about prepending
|
||||
// command with exec
|
||||
$p = $this->getProcess('exec php '.__DIR__.'/NonStopableProcess.php 3');
|
||||
$p->start();
|
||||
usleep(100000);
|
||||
$start = microtime(true);
|
||||
$p->stop(1.1);
|
||||
while ($p->isRunning()) {
|
||||
usleep(1000);
|
||||
}
|
||||
$duration = microtime(true) - $start;
|
||||
|
||||
$this->assertLessThan(1.3, $duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* tests results from sub processes
|
||||
*
|
||||
|
37
src/Symfony/Component/Process/Tests/NonStopableProcess.php
Normal file
37
src/Symfony/Component/Process/Tests/NonStopableProcess.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Runs a PHP script that can be stopped only with a SIGKILL (9) signal for 3 seconds
|
||||
*
|
||||
* @args duration Run this script with a custom duration
|
||||
*
|
||||
* @example `php NonStopableProcess.php 42` will run the script for 42 seconds
|
||||
*/
|
||||
|
||||
function handleSignal($signal)
|
||||
{
|
||||
switch ($signal) {
|
||||
case SIGTERM:
|
||||
$name = 'SIGTERM';
|
||||
break;
|
||||
case SIGINT:
|
||||
$name = 'SIGINT';
|
||||
break;
|
||||
default:
|
||||
$name = $signal . ' (unknown)';
|
||||
break;
|
||||
}
|
||||
|
||||
echo "received signal $name\n";
|
||||
}
|
||||
|
||||
declare(ticks=1);
|
||||
pcntl_signal(SIGTERM, 'handleSignal');
|
||||
pcntl_signal(SIGINT, 'handleSignal');
|
||||
|
||||
$duration = isset($argv[1]) ? (int) $argv[1] : 3;
|
||||
$start = microtime(true);
|
||||
|
||||
while ($duration > (microtime(true) - $start)) {
|
||||
usleep(1000);
|
||||
}
|
Reference in New Issue
Block a user