Skip to content

[Console] ConsoleEvents::SIGNAL subscriber not called #45332

@GwendolenLynch

Description

@GwendolenLynch

Symfony version(s) affected

5.2+

Description

The (awesome) console signal handling introduced in #33729 and #37827 seems to have some issues (or maybe it's just me 😺 ) with subscriber events:

  • Subscriber ConsoleEvents::SIGNAL events do not get called, but events such as ConsoleEvents::TERMINATE do
  • Listener events (command implementing SignalableCommandInterface) work, with one caveat;
    • if a subscriber exists, it will be called and the command's discrete handler ignored

How to reproduce

  1. Create a Symfony project symfony new --webapp symfony-pcntl-test

  2. Build the following classes

// src/Command/AbstractSignalCommand.php

abstract class AbstractSignalCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->title("Starting {$this->getName()} command execution");

        for ($i = 0; $i <10; ++$i) {
            $io->writeln('Tick ' . $i);
            sleep(1);
        }

        $io->success('Normal exit from command.');

        return Command::SUCCESS;
    }
}
// src/Command/SignalListenerCommand.php

#[AsCommand(
    name: 'app:signal:listener',
)]
class SignalListenerCommand extends AbstractSignalCommand implements SignalableCommandInterface
{
    public function getSubscribedSignals(): array
    {
        return [SIGINT];
    }

    public function handleSignal(int $signal): void
    {
        if (SIGINT === $signal) {
            dump('Caught a listener SIGINT');
            exit;
        }
    }
}
// src/Command/SignalSubscriberCommand.php

#[AsCommand(
    name: 'app:signal:subscriber',
)]
class SignalSubscriberCommand extends AbstractSignalCommand
{
}
// src/EventSubscriber/CommandSignalSubscriber.php

class CommandSignalSubscriber implements EventSubscriberInterface
{
    public function onConsoleSignal(ConsoleSignalEvent $event): void
    {
        if ($event->getHandlingSignal() === SIGINT) {
            dump('Caught a !!!subscriber!!! SIGINT');
            exit;
        }
    }

    public function onConsoleTerminate(ConsoleTerminateEvent $event)
    {
        dump('Handling normal termination event');
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ConsoleEvents::SIGNAL => 'onConsoleSignal',
            ConsoleEvents::TERMINATE => 'onConsoleTerminate',
        ];
    }
}
  1. Check event dispatcher
$ bin/console debug:event-dispatcher console.signal
# ...
 ------- ---------------------------------------------------------------- ---------- 
  Order   Callable                                                         Priority  
 ------- ---------------------------------------------------------------- ---------- 
  #1      App\EventSubscriber\CommandSignalSubscriber::onConsoleSignal()   0         
 ------- ---------------------------------------------------------------- -----------
  1. Run the listener enabled command and emit a CTRL+c
$ bin/console app:signal:listener

Starting app:signal:listener command execution
==============================================

Tick 0
Tick 1
^C"Caught a !!!subscriber!!! SIGINT"

NOTE: The handling of the signal is done in the subscriber here, but removing ConsoleEvents::SIGNAL from CommandSignalSubscriber::getSubscribedEvents will cause the handling to be done by the listener.

  1. Run the subscriber enabled command and emit a CTRL+c
$ bin/console app:signal:subscriber

Starting app:signal:subscriber command execution
================================================

Tick 0
Tick 1
^C

NOTE: Nothing handles the signal.

Possible Solution

No response

Additional Context

  • Tested on Symfony v6.0.4

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

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy