Skip to content

[Console] Commands aren't able to fully gracefully exit by themselves #47809

Closed
@lcobucci

Description

@lcobucci

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"}
$

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions