-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[FrameworkBundle] Catch Fatal errors in commands registration #23836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FrameworkBundle] Catch Fatal errors in commands registration #23836
Conversation
2f4ad61
to
56bd99a
Compare
return parent::doRun($input, $output); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
final protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
making it final when overwriting the method is a BC break. People extending the class were allowed to overwrite the method previously
private function renderRegistrationErrors(OutputInterface $output) | ||
{ | ||
$output->writeln('', OutputInterface::VERBOSITY_QUIET); | ||
$this->doRenderException(new CommandRegistrationFailedException('Some commands could not be registered.'), $output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use a RuntimeException instead of adding another exception
48b3ade
to
7dd1aaf
Compare
$this->doRenderException(new RuntimeException('Some commands could not be registered.'), $output); | ||
foreach ($this->registrationErrors as $error) { | ||
$this->doRenderException($error, $output); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should registrationErrors be resetted once rendered?
} | ||
|
||
/** | ||
* @internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd suggest removing this one: using things cross components/bundles is a trigger that this is not so internal anymore - cross-version constraints would anyway prevent doing non BC things here
do we care some commands could not be registered while running another command? When running the actual command i think 1 red block (the middle) is fine =/ |
@@ -70,12 +73,28 @@ public function doRun(InputInterface $input, OutputInterface $output) | |||
|
|||
$this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); | |||
|
|||
if ($this->registrationErrors) { | |||
$this->renderRegistrationErrors($output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, when trying to run the failing command which could not be registered thus doesn't exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but it will render in doRunCommand no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, doRunCommand
is never reached if the command cannot be found
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Still not sure whats populating registrationErrors :S id expected it to be set after parent::doRun.
https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/Console/Application.php#L216 being the trigger
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually it's triggered at application construction https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/Console/Application.php#L92 :) (calls add()
which then calls registerCommands()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hence these errors are actually uncaught, they prevent the app from being constructed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course :) thx.
Still.. this could also happen for lazy commands from the command loader. I dont think thats covered and happens in between currently...
edit: never mind... those are caught already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure to understand. Lazy command names are known beforehand and cannot fail before being ran since they are lazy, nothing to change for them to me
edit: just see your edit :)
unapplicable as the failure prevents knowing the name of the command |
Maybe simple and effective; just render all registration exceptions and abort the run. It's an invalid state and currently already crashes. Not sure tracking command<>exception is worth it in effort to run another valid command (this is new behavior ;-)). edit: omg.. this day :) it's feature request not a bugfix :) my bad. Still not sure about it though. |
that's exactly what this PR tries to fix: running |
You're right. i went over the related issue way to fast. But im not sure if linking exceptions from auto-discovery with command names is worth it, especially since thats going to be deprecated. Also warnings being red bites. |
we don't know what command failed since we don't have their names before they are successfully booted, so we have to display the warning + errors when running any valid command. |
7dd1aaf
to
ae844b3
Compare
PR updated, first exception replaced by a warning. |
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) | ||
{ | ||
if ($this->registrationErrors) { | ||
$this->renderRegistrationErrors($input, output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
ae844b3
to
26b0c95
Compare
26b0c95
to
ff67dd8
Compare
ff67dd8
to
46b6b42
Compare
(updated to make use of stderr when available) |
Thank you @chalasr. |
…tration (chalasr) This PR was merged into the 3.4 branch. Discussion ---------- [FrameworkBundle] Catch Fatal errors in commands registration | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #23610 | License | MIT | Doc PR | n/a #### before  #### after  Trying to run the failing command itself  Exceptions/errors thrown in `registerCommands()` (bundles/non-lazy command services registration) are caught and displayed as a warning, allowing to run other valid commands. Commits ------- 46b6b42 [FrameworkBundle] Catch Fatal errors in commands registration
🎉 |
before
after
Trying to run the failing command itself
Exceptions/errors thrown in
registerCommands()
(bundles/non-lazy command services registration) are caught and displayed as a warning, allowing to run other valid commands.