Skip to content
Browse files

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...
1 parent 7221d25 commit bec8ff16e8ec01e344811ec93d95ef0703b9ecfa @romainneutron committed Apr 6, 2013
View
6 src/Symfony/Component/Process/Process.php
@@ -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;
@@ -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);
}
View
25 src/Symfony/Component/Process/Tests/AbstractProcessTest.php
@@ -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
*
View
37 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.
Something went wrong with that request. Please try again.