Skip to content

[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

Merged
merged 1 commit into from
Aug 10, 2017

Conversation

chalasr
Copy link
Member

@chalasr chalasr commented Aug 9, 2017

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

before

after

after

Trying to run the failing command itself

failing

Exceptions/errors thrown in registerCommands() (bundles/non-lazy command services registration) are caught and displayed as a warning, allowing to run other valid commands.

@chalasr chalasr added the DX DX = Developer eXperience (anything that improves the experience of using Symfony) label Aug 9, 2017
@chalasr chalasr force-pushed the console/catch-unregistrable-command branch from 2f4ad61 to 56bd99a Compare August 9, 2017 08:53
return parent::doRun($input, $output);
}

/**
* {@inheritdoc}
*/
final protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
Copy link
Member

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);
Copy link
Member

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

@chalasr chalasr force-pushed the console/catch-unregistrable-command branch 2 times, most recently from 48b3ade to 7dd1aaf Compare August 9, 2017 09:31
$this->doRenderException(new RuntimeException('Some commands could not be registered.'), $output);
foreach ($this->registrationErrors as $error) {
$this->doRenderException($error, $output);
}
Copy link
Member

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
Copy link
Member

@nicolas-grekas nicolas-grekas Aug 9, 2017

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

@ro0NL
Copy link
Contributor

ro0NL commented Aug 9, 2017

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this happen?

Copy link
Member Author

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

Copy link
Contributor

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?

Copy link
Member Author

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

Copy link
Contributor

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

Copy link
Member Author

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())

Copy link
Member Author

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

Copy link
Contributor

@ro0NL ro0NL Aug 9, 2017

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.

Copy link
Member Author

@chalasr chalasr Aug 9, 2017

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 :)

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Aug 9, 2017

I agree with @ro0NL about the "1 red block is enough". We could just list the command that fail to be loaded, and not display the corresponding exception. But then, when that failing command is run, we should display the exception of course. WDYT?

unapplicable as the failure prevents knowing the name of the command

@ro0NL
Copy link
Contributor

ro0NL commented Aug 9, 2017

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.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Aug 9, 2017

worth it in effort to run another valid command

that's exactly what this PR tries to fix: running cache:clear while some other commands are broken. So YES, it's worth the effort :)

@ro0NL
Copy link
Contributor

ro0NL commented Aug 9, 2017

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.

@chalasr
Copy link
Member Author

chalasr commented Aug 9, 2017

do we care some commands could not be registered while running another command?

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.

@chalasr chalasr force-pushed the console/catch-unregistrable-command branch from 7dd1aaf to ae844b3 Compare August 9, 2017 13:20
@chalasr
Copy link
Member Author

chalasr commented Aug 9, 2017

PR updated, first exception replaced by a warning.

protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
{
if ($this->registrationErrors) {
$this->renderRegistrationErrors($input, output);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$output

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops

@chalasr chalasr force-pushed the console/catch-unregistrable-command branch from ae844b3 to 26b0c95 Compare August 9, 2017 15:22
@chalasr chalasr force-pushed the console/catch-unregistrable-command branch from 26b0c95 to ff67dd8 Compare August 9, 2017 16:37
@chalasr chalasr force-pushed the console/catch-unregistrable-command branch from ff67dd8 to 46b6b42 Compare August 9, 2017 16:38
@chalasr
Copy link
Member Author

chalasr commented Aug 9, 2017

(updated to make use of stderr when available)

@chalasr chalasr added this to the 3.4 milestone Aug 9, 2017
@fabpot
Copy link
Member

fabpot commented Aug 10, 2017

Thank you @chalasr.

@fabpot fabpot merged commit 46b6b42 into symfony:3.4 Aug 10, 2017
fabpot added a commit that referenced this pull request Aug 10, 2017
…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

![before](https://image.prntscr.com/image/QDmEVSPiQY6VCY7PoNAIbg.png)

#### after

![after](https://image.prntscr.com/image/B2EuZtzwTfiVS6F3kTAa4Q.png)

Trying to run the failing command itself

![failing](https://image.prntscr.com/image/7RgdtCVyQXyVit8TPkh98A.png)

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
@chalasr chalasr deleted the console/catch-unregistrable-command branch August 10, 2017 07:25
@jean-pasqualini
Copy link
Contributor

🎉

This was referenced Oct 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DX DX = Developer eXperience (anything that improves the experience of using Symfony) Feature FrameworkBundle Status: Needs Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants