-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Restore exception handler after running it #13686
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
Conversation
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.
👍 makes sense to me thanks.
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 didn't understand the test (it behaves as expected without the patch) and its relation to the bug report.
Right, this still needs a better test. I'll add one later today. This test was added to make sure an executing closure doesn't get released prematurely (I wasn't sure about this behavior when implementing this, so I made sure it didn't break). |
Symfony relies on finding the exception handler in the handler stack. There's currently no clean API to find it, so they pop all the handlers, and push them again once the stack is empty. This PR attempts to minimize the BC break by pushing the current handler onto the stack and clearing the current handler, and restoring it once it has finished. This is essentially equivalent to set_exception_handler(null) and restore_exception_handler(). restore_exception_handler() however is only called if the exception handler is still unset. If the handler has pushed a new handler in the meantime, we assume it knows what it's doing. Fixes phpGH-13446
This change is causing this code to recurse infinitely in PHP 8.3.5+: https://3v4l.org/Hct7c. Similar construct is used in Yii's exception handler here. Is that a desired behavior? On the other hand, this code https://3v4l.org/ARJ9A works like I would expect it to on 8.3.0-8.3.4, doesn't work like I would expect on PHPs < 8.3, but causes infinite recursion on 8.3.5+. Only this code https://3v4l.org/NNnEA seems to work consistently for all PHPs 8.3.x. |
@lavarou Yes. Since PHP 8.3, calling the error handler involves replacing the error handler with What's the reason for calling Looking at Yiis comment:
I don't think that was ever a concern. Previously, PHP just didn't call error handlers at all after a fatal error has already occurred. Edit: I see it also disables the error handler, which might be the more relevant part. |
@iluuu1994 Thank you for your prompt response and providing more details.
I cannot answer this question as I'm neither Yii user nor Yii developer. I just wanted to provide some examples of the PHP code where the changes around exception handling in PHP 8.3 demonstrate different behaviors between versions in case any future PHP developer will be curious how things work and what to expect. |
Thanks. The change to call the exception handler again (when re-registered) was made in PHP 8.3. However, it did not actually store the called error handler on the stack, it was just discarded. This was later improved in PHP 8.3.5, so that restoring the error handler would pop the current error handler in-place again. I did not anticipate this breaking any code. However, I think adjusting this again would just further risk breaking more code, so I would prefer keeping things as-is. |
Symfony relies on finding the exception handler in the handler stack. There's currently no clean API to find it, so they pop all the handlers, and push them again once the stack is empty. This PR attempts to minimize the BC break by pushing the current handler onto the stack and clearing the current handler, and restoring it once it has finished. This is essentially equivalent to set_exception_handler(null) and restore_exception_handler().
restore_exception_handler() however is only called if the exception handler is still unset. If the handler has pushed a new handler in the meantime, we assume it knows what it's doing.
Fixes GH-13446
/cc @nicolas-grekas Does this solve your problem?