Closed
Description
Symfony version(s) affected
5.2.0+
Description
Since df57119 symfony/console is reacting to signals, dispatching events, and exiting right away.
My main issue here is the exit()
inside of the signal handler, as it imposes a specific application design for graceful shutdowns and prevents the dispatch of console.terminate
event.
How to reproduce
A command like this should suffice:
<?php
declare(strict_types=1);
namespace MyApp;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\SignalableCommandInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function sleep;
use const SIGINT;
use const SIGTERM;
#[AsCommand('testing')]
final class Testing extends Command implements SignalableCommandInterface
{
private bool $shouldContinue = true;
protected function execute(InputInterface $input, OutputInterface $output): int
{
while ($this->shouldContinue) {
$output->writeln('Still processing...');
sleep(1);
}
$output->writeln('Wrapping up, wait a sec...'); // this message is never shown (unless we remove the `exit()` call)
return self::SUCCESS;
}
public function getSubscribedSignals(): array
{
return [SIGINT, SIGTERM];
}
public function handleSignal(int $signal): void
{
$this->shouldContinue = false;
}
}
Possible Solution
I believe Symfony should not auto exit on that situation or at least provide a way to skip it.
Additional Context
Execution of the sample command with the exit()
:
$ bin/console testing
{"message":"Notified event \"console.command\" to listener \"Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener::configure\".","context":{"event":"console.command","listener":"Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener::configure"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:12:24.056+00:00"}
{"message":"Notified event \"console.command\" to listener \"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onCommand\".","context":{"event":"console.command","listener":"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onCommand"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:12:24.056+00:00"}
Still processing...
Still processing...
Still processing...
Still processing...
^C $
Execution of the sample command without the exit()
:
$ bin/console testing
{"message":"Notified event \"console.command\" to listener \"Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener::configure\".","context":{"event":"console.command","listener":"Symfony\\Component\\HttpKernel\\EventListener\\DebugHandlersListener::configure"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:13:39.000+00:00"}
{"message":"Notified event \"console.command\" to listener \"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onCommand\".","context":{"event":"console.command","listener":"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onCommand"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:13:39.000+00:00"}
Still processing...
Still processing...
Still processing...
^CWrapping up, wait a sec...
{"message":"Notified event \"console.terminate\" to listener \"Symfony\\Component\\Console\\EventListener\\ErrorListener::onConsoleTerminate\".","context":{"event":"console.terminate","listener":"Symfony\\Component\\Console\\EventListener\\ErrorListener::onConsoleTerminate"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:13:41.554+00:00"}
{"message":"Notified event \"console.terminate\" to listener \"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onTerminate\".","context":{"event":"console.terminate","listener":"Symfony\\Bridge\\Monolog\\Handler\\ConsoleHandler::onTerminate"},"channel":"event","severity":"DEBUG","timestamp":"2022-10-07T10:13:41.554+00:00"}
$