Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Console] Unexpected behavior on CONTROL-C #48340

Closed
@olegpro

Description

@olegpro

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