[4.0] Fix use of Symfony ErrorHandler, and update error handling in general#27632
[4.0] Fix use of Symfony ErrorHandler, and update error handling in general#27632wilsonge merged 7 commits intojoomla:4.0-devfrom
Conversation
|
No more commented constants that have to be edited in code to access. Use the system configuration for this or don’t introduce a new behavior. Also, do not judge the use based solely on naming. This may very well be the correct way to configure the component, or the rendering logic may require additional adjustments to do right. |
| } | ||
| finally | ||
| { | ||
| throw $e; |
There was a problem hiding this comment.
You’re better off using Reflection to alter the Exception properties than trying this black hat trickery. No way anyone can actually read and understand what this try/finally block is actually doing.
There was a problem hiding this comment.
Reflection was a first thing I tried, but I got another Exception "Property previous not exist" when doing:
$refl = new ReflectionClass($e);
$property = $refl->getProperty('previous');
Try/finally is one that work, it "collect" exceptions
There was a problem hiding this comment.
That’s not a valid way of “collecting” Exceptions. At that point one can not evaluate the code and determine what is the intended order of operations or the intended end result, you’re basically relying on some magic and probably undocumented PHP behavior and that is too risky.
You’re better off rethrowing the original Exception without the error page exception than trying this trickery.
There was a problem hiding this comment.
You just do not like a magic :-p
Because it not documented it does not means that it "not a valid", there many stuf undocumented, whole "finally" documentation has only 1-2 sentence.
As long as it works and allow to see nested exceptions it is okay, this is better than hiding errors that not possible to debug later.
I do not see any big risk in this particular case.
There was a problem hiding this comment.
Relying on magic behaviors or undocumented engine behaviors is what gets you in trouble later on. Code is ALWAYS more stable if it has a predictable behavior, AFAIK this behavior is not specified in the RFC introducing finally support to PHP or any documentation detailing its use. Inherently this means it is a risky behavior to use as it may very well not be an engine design but something that works by accident in the way you want it to.
There was a problem hiding this comment.
I found at least 2 test cases for this behavior:
exactly for this case : https://github.com/php/php-src/blob/master/Zend/tests/try/try_finally_002.phpt
and more complex case: https://github.com/php/php-src/blob/master/Zend/tests/try/catch_finally_004.phpt
Does not looks like a random engine behavior, which has test cases, or?
This part of the exception nesting API. There zero detail about it, but it does not means that it wrong.
I think it pretty stable code to use, I will leave it.
One issue I see that not all may understand how it work, but that not a code problem.
There was a problem hiding this comment.
If you’re going to insist on keeping it this way (I’m not a fan of it but whatever) then the comment block for this needs to be a lot more clear about what it’s doing then. Because it’s not really helping to explain what you’re doing here at all or what the end result you’re creating is.
Yeah, but I have no idea here, configuration.php not possible to use at this point.
What do you mean? I not very understood. |
If you reviewed the component then you’d know that by default it is in a state where only an error message is printed, there is no need for extra configuration except to enable additional debug information. To me this PR comes across as someone not really understanding the code attempting to make changes for the sake of change. The only tangible benefit is the rethrow if rendering the error page fails but that code is convoluted and impossible to actually follow what the intended behaviors are. |
I’m saying don’t introduce a new conditionally defined constant that someone has to edit a file to enable. Use the configuration. The reason I never enabled debug output is because of the problem you noted, adding new constants doesn’t fix the bootstrapping problem (because ultimately the issue here is things are not loaded in a usable order, load it all in the right order and the need for a conditional constant goes away).
You’re saying it’s wrong based solely on the fact the class is named “renderer”. I’m saying that might not be the case. |
I am actually disabling it, because it enabled by default:
I did not made this conclusion by reviewing the name, that would be not very smart. 😃 |
Then it should respect the error handling configuration, not be an all or nothing thing or based on a hidden configuration flag. Which still means the load order needs to be fixed. |
|
I have made Error Handler configurable, without additional constant. Should be better now. |
That's not really true? https://github.com/symfony/symfony/blob/master/src/Symfony/Component/ErrorHandler/ErrorHandler.php#L149 The renderer is still the default exception handler in your code - you just aren't calling it explicitely ;) However I think largely the changes your making here are on the right lines - although I agree with Michael to an extent - the changes you are making to the exception handler are really confusing to me :D There has to be a cleaner way of dealing with it? |
That confusing part 😄
You mean nested exception? I think it okay, Learning something new it is okay :) |
|
here is a better explanation https://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html#finally-handling
|
|
And I believe it part of this RFC (Implemented) https://wiki.php.net/rfc/finally wich has the same test files, unfortunately they lost in history. |
libraries/bootstrap.php
Outdated
|
|
||
| // Make sure we do not display sensitive data in production environments | ||
| // Disable a detailed error message by default | ||
| $errorHandler->scopeAt(0, true); |
There was a problem hiding this comment.
I would still flat out remove this line. There’s no reason for the libraries bootstrap to make this opinionated of a decision without having the system configuration available. About the only acceptable default at this point in the bootup sequence to me would be to match the scope to the current error_reporting settings, which would be coming from the server’s PHP configuration.
|
I have updated comments, and use server error_reporting for initial set up. |
|
Can we have some errors here please? I meant a tests 🙃 |
|
Merging this on review for now. Seems to have addressed @mbabker 's comments and I think he knows more of this than I clearly do :) |
Summary of Changes
@wilsonge I found an issue in #27470 😉
You have set
HtmlErrorRendererasExceptionHandlerthat incorrect of course, because it a rendered not a handler 😉.I have fixed it here.
And because ErrorHandler may show whole error detail on production environment I have disable it by default, a full trace may be enabled by enabling debug or changing "display errors" option in global config
Additionally I have made changes to Joomla\ExceptionHandler, now it will use global ExceptionHandler as "last resort", which allow to do a better debugging, now it also pre-save a full trace of both exceptions, instead of old useless "Error" message.
Testing Instructions
First step:
To test need to emulate a "heavy crash", for this add 2 exception to the cassiopeia template:
First in
index.php:throw new Exception('The main error!');Second at top of
error.php:throw new Exception('The error of the error!');Then go to the site, you should see the error:

Second step:

Go to administrator global configuration and set "Display Error" to "maximum", or enable "Debug"
Then go to the site, you should see detailed information about all exceptions that occurred:
(click on little +)
@mbabker please have a look also