Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix timeout in Process::stop method
 - The timeout is ten times more than set.
 - The timeout does not occurs, it is actually blocking until the process dies.
  • Loading branch information
romainneutron committed Apr 7, 2013
1 parent 7221d25 commit bec8ff1
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/Symfony/Component/Process/Process.php
Expand Up @@ -591,7 +591,7 @@ public function isRunning()
*/
public function stop($timeout=10)
{
$timeoutMicro = (int) $timeout*10E6;
$timeoutMicro = (int) $timeout*1E6;
if ($this->isRunning()) {
proc_terminate($this->process);
$time = 0;
Expand All @@ -600,6 +600,10 @@ public function stop($timeout=10)
usleep(1000);
}

if (!defined('PHP_WINDOWS_VERSION_BUILD') && $this->isRunning()) {
proc_terminate($this->process, SIGKILL);
}

foreach ($this->pipes as $pipe) {
fclose($pipe);
}
Expand Down
25 changes: 25 additions & 0 deletions src/Symfony/Component/Process/Tests/AbstractProcessTest.php
Expand Up @@ -44,6 +44,31 @@ public function testNullTimeout()
$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
*
Expand Down
37 changes: 37 additions & 0 deletions src/Symfony/Component/Process/Tests/NonStopableProcess.php
@@ -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);
}

0 comments on commit bec8ff1

Please sign in to comment.