Skip to content

Commit df0a963

Browse files
committed
[Process] Add support for posix signals
1 parent b62d1dd commit df0a963

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Process\Exception;
13+
14+
/**
15+
* LogicException for the Process Component.
16+
*
17+
* @author Romain Neutron <imprec@gmail.com>
18+
*/
19+
class LogicException extends \LogicException implements ExceptionInterface
20+
{
21+
}

src/Symfony/Component/Process/Process.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Component\Process;
1313

14+
use Symfony\Component\Process\Exception\LogicException;
15+
use Symfony\Component\Process\Exception\RuntimeException;
16+
1417
/**
1518
* Process is a thin wrapper around proc_* functions to ease
1619
* start independent PHP processes.
@@ -361,7 +364,7 @@ public function wait($callback = null)
361364
}
362365
$this->updateStatus();
363366
if ($this->processInformation['signaled']) {
364-
throw new \RuntimeException(sprintf('The process stopped because of a "%s" signal.', $this->processInformation['stopsig']));
367+
throw new RuntimeException(sprintf('The process stopped because of a "%s" signal.', $this->processInformation['stopsig']));
365368
}
366369

367370
$time = 0;
@@ -551,6 +554,33 @@ public function getPid()
551554
return $this->isRunning() ? $this->processInformation['pid'] : null;
552555
}
553556

557+
/**
558+
* Send a posix signal to the process
559+
*
560+
* @param integer $sig A valid posix signal (see http://www.php.net/manual/en/pcntl.constants.php)
561+
* @return Process
562+
*
563+
* @throws LogicException In case the process is not running
564+
* @throws RuntimeException In case the environment does not support posix signals
565+
* @throws RuntimeException In case of failure
566+
*/
567+
public function sendSignal($sig)
568+
{
569+
if (!$this->isRunning()) {
570+
throw new LogicException('Can not send signal on a non running process');
571+
}
572+
573+
if (!extension_loaded('posix')) {
574+
throw new RuntimeException('Posix extension is required to send signals');
575+
}
576+
577+
if (true !== posix_kill($this->getPid(), $sig)) {
578+
throw new RuntimeException(sprintf('Error while sending signal : %s', posix_strerror(posix_get_last_error())));
579+
}
580+
581+
return $this;
582+
}
583+
554584
/**
555585
* Stops the process.
556586
*

src/Symfony/Component/Process/Tests/ProcessTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Process\Tests;
1313

1414
use Symfony\Component\Process\Process;
15+
use Symfony\Component\Process\Exception\RuntimeException;
1516

1617
/**
1718
* @author Robert Schönthal <seroscho@googlemail.com>
@@ -151,6 +152,43 @@ public function testGetPid()
151152
$this->assertNull($process->getPid());
152153
}
153154

155+
public function testSendSignal()
156+
{
157+
$process = new Process('php -r "sleep(1);');
158+
$process->start();
159+
$process->sendSignal(SIGCONT);
160+
$process->stop();
161+
}
162+
163+
/**
164+
* @expectedException Symfony\Component\Process\Exception\RuntimeException
165+
*/
166+
public function testSendKillSignal()
167+
{
168+
$process = new Process('php -r "sleep(1);');
169+
$process->start();
170+
$process->sendSignal(SIGKILL);
171+
$process->wait();
172+
}
173+
174+
public function testSendKillSignalAndCatch()
175+
{
176+
$process = new Process('php -r "sleep(1);');
177+
$process->start();
178+
$process->sendSignal(SIGKILL);
179+
180+
try {
181+
$process->wait();
182+
$this->fail('Should throw an exception as the signal stops the process');
183+
} catch (RuntimeException $e) {
184+
185+
}
186+
187+
$this->assertFalse($process->isRunning());
188+
$this->assertTrue($process->hasBeenSignaled());
189+
$this->assertEquals(SIGKILL, $process->getTermSignal());
190+
}
191+
154192
public function testStop()
155193
{
156194
$process = new Process('php -r "while (true) {}"');

0 commit comments

Comments
 (0)