From b62d1dd4525ba55d6f5199abf945e089602e7692 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 30 Aug 2012 15:37:34 +0200 Subject: [PATCH 1/3] [Process] Add a getPid method for process --- src/Symfony/Component/Process/Process.php | 12 ++++++++++++ src/Symfony/Component/Process/Tests/ProcessTest.php | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index cd1e8b42155a2..fed76a646e528 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -539,6 +539,18 @@ public function isRunning() return $this->processInformation['running']; } + /** + * Return the Pid (process id), if applicable + * + * @return integer|null The process id if running, null otherwise + */ + public function getPid() + { + $this->updateStatus(); + + return $this->isRunning() ? $this->processInformation['pid'] : null; + } + /** * Stops the process. * diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 64f929cc20d61..aacf6702700af 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -141,6 +141,16 @@ public function testIsRunning() $this->assertFalse($process->isRunning()); } + public function testGetPid() + { + $process = new Process('php -r "sleep(1);"'); + $this->assertNull($process->getPid()); + $process->start(); + $this->assertGreaterThan(0, $process->getPid()); + $process->wait(); + $this->assertNull($process->getPid()); + } + public function testStop() { $process = new Process('php -r "while (true) {}"'); From df0a963dbd0e46ff4a469da67c92b90e9b07661d Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 31 Aug 2012 00:52:28 +0200 Subject: [PATCH 2/3] [Process] Add support for posix signals --- .../Process/Exception/LogicException.php | 21 ++++++++++ src/Symfony/Component/Process/Process.php | 32 +++++++++++++++- .../Component/Process/Tests/ProcessTest.php | 38 +++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Process/Exception/LogicException.php diff --git a/src/Symfony/Component/Process/Exception/LogicException.php b/src/Symfony/Component/Process/Exception/LogicException.php new file mode 100644 index 0000000000000..be3d490dde8cd --- /dev/null +++ b/src/Symfony/Component/Process/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Exception; + +/** + * LogicException for the Process Component. + * + * @author Romain Neutron + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index fed76a646e528..2ee2b074d11a4 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Process; +use Symfony\Component\Process\Exception\LogicException; +use Symfony\Component\Process\Exception\RuntimeException; + /** * Process is a thin wrapper around proc_* functions to ease * start independent PHP processes. @@ -361,7 +364,7 @@ public function wait($callback = null) } $this->updateStatus(); if ($this->processInformation['signaled']) { - throw new \RuntimeException(sprintf('The process stopped because of a "%s" signal.', $this->processInformation['stopsig'])); + throw new RuntimeException(sprintf('The process stopped because of a "%s" signal.', $this->processInformation['stopsig'])); } $time = 0; @@ -551,6 +554,33 @@ public function getPid() return $this->isRunning() ? $this->processInformation['pid'] : null; } + /** + * Send a posix signal to the process + * + * @param integer $sig A valid posix signal (see http://www.php.net/manual/en/pcntl.constants.php) + * @return Process + * + * @throws LogicException In case the process is not running + * @throws RuntimeException In case the environment does not support posix signals + * @throws RuntimeException In case of failure + */ + public function sendSignal($sig) + { + if (!$this->isRunning()) { + throw new LogicException('Can not send signal on a non running process'); + } + + if (!extension_loaded('posix')) { + throw new RuntimeException('Posix extension is required to send signals'); + } + + if (true !== posix_kill($this->getPid(), $sig)) { + throw new RuntimeException(sprintf('Error while sending signal : %s', posix_strerror(posix_get_last_error()))); + } + + return $this; + } + /** * Stops the process. * diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index aacf6702700af..92374fbdc8443 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Process\Tests; use Symfony\Component\Process\Process; +use Symfony\Component\Process\Exception\RuntimeException; /** * @author Robert Schönthal @@ -151,6 +152,43 @@ public function testGetPid() $this->assertNull($process->getPid()); } + public function testSendSignal() + { + $process = new Process('php -r "sleep(1);'); + $process->start(); + $process->sendSignal(SIGCONT); + $process->stop(); + } + + /** + * @expectedException Symfony\Component\Process\Exception\RuntimeException + */ + public function testSendKillSignal() + { + $process = new Process('php -r "sleep(1);'); + $process->start(); + $process->sendSignal(SIGKILL); + $process->wait(); + } + + public function testSendKillSignalAndCatch() + { + $process = new Process('php -r "sleep(1);'); + $process->start(); + $process->sendSignal(SIGKILL); + + try { + $process->wait(); + $this->fail('Should throw an exception as the signal stops the process'); + } catch (RuntimeException $e) { + + } + + $this->assertFalse($process->isRunning()); + $this->assertTrue($process->hasBeenSignaled()); + $this->assertEquals(SIGKILL, $process->getTermSignal()); + } + public function testStop() { $process = new Process('php -r "while (true) {}"'); From 0adee2220194b22470431edc1ee7cd98660b35a7 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 7 Sep 2012 22:46:29 +0200 Subject: [PATCH 3/3] Rename sendSignal to signal, use proc_terminate instead of posix_kill --- src/Symfony/Component/Process/Process.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 2ee2b074d11a4..b418175d4e969 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -557,25 +557,21 @@ public function getPid() /** * Send a posix signal to the process * - * @param integer $sig A valid posix signal (see http://www.php.net/manual/en/pcntl.constants.php) + * @param integer $signal A valid posix signal (see http://www.php.net/manual/en/pcntl.constants.php) * @return Process * * @throws LogicException In case the process is not running * @throws RuntimeException In case the environment does not support posix signals * @throws RuntimeException In case of failure */ - public function sendSignal($sig) + public function signal($signal) { if (!$this->isRunning()) { throw new LogicException('Can not send signal on a non running process'); } - if (!extension_loaded('posix')) { - throw new RuntimeException('Posix extension is required to send signals'); - } - - if (true !== posix_kill($this->getPid(), $sig)) { - throw new RuntimeException(sprintf('Error while sending signal : %s', posix_strerror(posix_get_last_error()))); + if (true !== proc_terminate($this->process, $signal)) { + throw new RuntimeException('Error while sending signal'); } return $this;