Description
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:
\Symfony\Component\Messenger\Worker::run
added to the bottomfwrite(\STDOUT, PHP_EOL . 'worker stop' . PHP_EOL);
\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