Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Console] Unexpected behavior on CONTROL-C #48340

Copy link
Copy link
Closed
@olegpro

Description

@olegpro
Issue body actions

Symfony version(s) affected

6.1.x

Description

Unexpected behavior on CONTROL-C in symfony/console & symfony/messenger

How to reproduce

Before testing, I modified a few files:

  1. \Symfony\Component\Messenger\Worker::run added to the bottom fwrite(\STDOUT, PHP_EOL . 'worker stop' . PHP_EOL);
  2. \Symfony\Component\Messenger\Command\ConsumeMessagesCommand::execute before return $io->comment('Quit');

Next run:

$ docker-compose exec php bin/console messenger:consume async -vvv
                                                                                                                      
 [OK] Consuming messages from transports "async".                                                                       
                                                                                                                        

 // The worker will automatically exit once it has received a stop signal via the messenger:stop-workers command.       

 // Quit the worker with CONTROL-C.   

and pay attention to the phrase "Quit the worker with CONTROL-C."

After that, in the same terminal, I press CONTROL-C. and the consumer terminates unexpectedly without outputting to stdout, which I modified above in the source code. There will be only ^C in the console. Full log:

$ docker-compose exec php bin/console messenger:consume async -vvv

                                                                                                                        
 [OK] Consuming messages from transports "async".                                                                       
                                                                                                                        

 // The worker will automatically exit once it has received a stop signal via the messenger:stop-workers command.       

 // Quit the worker with CONTROL-C.                                                                                     

^C

And if you open a second terminal with docker-compose exec php sh and call kill pid, then the consumer will exit:

13:08:59 INFO      [app] Received SIGTERM signal.
[
  "transport_names" => [
    "async"
  ]
]
[
  "uid" => "b66f4c45f3bba98ac04cd5dcc3db6968"
]
13:08:59 INFO      [messenger] Stopping worker.
[
  "transport_names" => [
    "async"
  ]
]
[
  "uid" => "b66f4c45f3bba98ac04cd5dcc3db6968"
]

worker stop
 // Quit  

Full log:

$ docker-compose exec php bin/console messenger:consume async -vvv

                                                                                                                        
 [OK] Consuming messages from transports "async".                                                                       
                                                                                                                        

 // The worker will automatically exit once it has received a stop signal via the messenger:stop-workers command.       

 // Quit the worker with CONTROL-C.                                                                                     

13:08:59 INFO      [app] Received SIGTERM signal.
[
  "transport_names" => [
    "async"
  ]
]
[
  "uid" => "b66f4c45f3bba98ac04cd5dcc3db6968"
]
13:08:59 INFO      [messenger] Stopping worker.
[
  "transport_names" => [
    "async"
  ]
]
[
  "uid" => "b66f4c45f3bba98ac04cd5dcc3db6968"
]

worker stop
 // Quit   

Is this the expected behavior for us?

For example, the event WorkerStoppedEvent will never be called (and ConsoleTerminateEvent).


The reason is exit(0) in \Symfony\Component\Console\Application::doRunCommand in this section::

            if (null !== $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);
                            }
                        }
                    });
                }
            }

If you remove exit(0), the result will be the same as with kill pid.


Thanks!

If this is legal behavior, then how do I solve the problem of missing WorkerStoppedEvent/ConsoleTerminateEvent events?

Possible Solution

No response

Additional Context

docker-image — php:8.1.11-fpm-alpine
symfony/console — 6.1.7
symfony/messenger — 6.1.6

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

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.