[Console] Register signal handling only for commands implemeting SignalableCommandInterface
Actually, it does not make sens to listen all signals for all commands. This commit also add more test for this part of code.
This commit is contained in:
parent
982bf9487e
commit
37b1faec8c
@ -286,23 +286,6 @@ class Application implements ResetInterface
|
||||
$command = $this->find($alternative);
|
||||
}
|
||||
|
||||
if ($this->dispatcher && $this->signalRegistry) {
|
||||
foreach ($this->signalsToDispatchEvent as $signal) {
|
||||
$event = new ConsoleSignalEvent($command, $input, $output, $signal);
|
||||
|
||||
$this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) {
|
||||
$this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
|
||||
|
||||
// No more handlers, we try to simulate PHP default behavior
|
||||
if (!$hasNext) {
|
||||
if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$this->runningCommand = $command;
|
||||
$exitCode = $this->doRunCommand($command, $input, $output);
|
||||
$this->runningCommand = null;
|
||||
@ -961,6 +944,24 @@ class Application implements ResetInterface
|
||||
if (!$this->signalRegistry) {
|
||||
throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
|
||||
}
|
||||
|
||||
if ($this->dispatcher) {
|
||||
foreach ($this->signalsToDispatchEvent as $signal) {
|
||||
$event = new ConsoleSignalEvent($command, $input, $output, $signal);
|
||||
|
||||
$this->signalRegistry->register($signal, function ($signal, $hasNext) use ($event) {
|
||||
$this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
|
||||
|
||||
// No more handlers, we try to simulate PHP default behavior
|
||||
if (!$hasNext) {
|
||||
if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], true)) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($command->getSubscribedSignals() as $signal) {
|
||||
$this->signalRegistry->register($signal, [$command, 'handleSignal']);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Console\Tests;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Command\SignalableCommandInterface;
|
||||
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
|
||||
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
@ -1808,6 +1809,39 @@ class ApplicationTest extends TestCase
|
||||
$app->setCommandLoader($loader);
|
||||
$app->get('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension pcntl
|
||||
*/
|
||||
public function testSignal()
|
||||
{
|
||||
$command = new SignableCommand();
|
||||
|
||||
$dispatcherCalled = false;
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addListener('console.signal', function () use (&$dispatcherCalled) {
|
||||
$dispatcherCalled = true;
|
||||
});
|
||||
|
||||
$application = new Application();
|
||||
$application->setAutoExit(false);
|
||||
$application->setDispatcher($dispatcher);
|
||||
$application->setSignalsToDispatchEvent(SIGALRM);
|
||||
$application->add($command);
|
||||
|
||||
$this->assertFalse($command->signaled);
|
||||
$this->assertFalse($dispatcherCalled);
|
||||
|
||||
$this->assertSame(0, $application->run(new ArrayInput(['signal'])));
|
||||
$this->assertFalse($command->signaled);
|
||||
$this->assertFalse($dispatcherCalled);
|
||||
|
||||
$command->loop = 100000;
|
||||
pcntl_alarm(1);
|
||||
$this->assertSame(1, $application->run(new ArrayInput(['signal'])));
|
||||
$this->assertTrue($command->signaled);
|
||||
$this->assertTrue($dispatcherCalled);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomApplication extends Application
|
||||
@ -1865,3 +1899,33 @@ class DisabledCommand extends Command
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SignableCommand extends Command implements SignalableCommandInterface
|
||||
{
|
||||
public $signaled = false;
|
||||
public $loop = 100;
|
||||
|
||||
protected static $defaultName = 'signal';
|
||||
|
||||
public function getSubscribedSignals(): array
|
||||
{
|
||||
return [SIGALRM];
|
||||
}
|
||||
|
||||
public function handleSignal(int $signal): void
|
||||
{
|
||||
$this->signaled = true;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
for ($i = 0; $i < $this->loop; ++$i) {
|
||||
usleep(100);
|
||||
if ($this->signaled) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user