Skip to content

[RFC] Add get_error_handler(), get_exception_handler() functions #17693

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

Closed
wants to merge 4 commits into from

Conversation

arnaud-lb
Copy link
Member

@arnaud-lb arnaud-lb commented Feb 4, 2025

Currently, the only way to fetch the current error and exception handlers is to push a new one before restoring it:

$current_error_handler = set_error_handler('valid_callback');
restore_error_handler();

This PR adds get_error_handler(), get_exception_handler() functions to address this use-case. They return the last value passed to set_error_handler() or set_exception_handler(), respectively, or NULL if no handler was set.

RFC: https://wiki.php.net/rfc/get-error-exception-handler

Related: symfony/symfony#58372 (comment).

cc @lyrixx @nicolas-grekas

@nielsdos
Copy link
Member

nielsdos commented Feb 4, 2025

I believe you can use RETURN_COPY instead of RETURN_ZVAL because those handlers can't be references, so the generated code will be a bit shorter by using RETURN_COPY then.

@TimWolla TimWolla added the RFC label Mar 19, 2025
@arnaud-lb arnaud-lb marked this pull request as ready for review March 21, 2025 17:18
@arnaud-lb arnaud-lb requested a review from kocsismate as a code owner March 21, 2025 17:18
@arnaud-lb arnaud-lb requested review from Girgias and nielsdos March 21, 2025 17:19
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

The implementation makes sense to me, I wonder however if as a follow-up we should refactor how the error/exceptions handlers are stored (e.g. as an FCC instead of a zval) so that we can return a Closure that is guaranteed to always be valid.

As callable still has scope implications and I'm not actually sure returning it as is necessarily makes it callable in the scope these new functions are called.

@jorgsowa
Copy link
Contributor

Does it make sense to add two test cases?

  1. get_error_handler() == get_error_handler()
  2. Invoking get_error_handler() without prior change of error handler.

And the same for get_exception_handler()

@arnaud-lb
Copy link
Member Author

@Girgias

I wonder however if as a follow-up we should refactor how the error/exceptions handlers are stored (e.g. as an FCC instead of a zval) so that we can return a Closure that is guaranteed to always be valid

Unfortunately I can not change that because the behaviour is specified explicitly in the RFC: "The returned handler is the exact callback value that was passed to set_error_handler() or set_exception_handler() to define it". It's useful, as this makes it possible to inspect the error handler and to compare it against known values. There are some examples here, here, or here.

Is the scope the only issue making the value potentially not callable? An alternative solution to that problem may be to change set_error_handler so that it accepts only callables that are valid in any scope.

Currently, set_error_handler accepts anything that's callable from the current scope, but zend_error_zstr_at() may fail to call the handler later, from a different scope.

@janedbal
Copy link

Any plans adding also get_shutdown_handlers?

@arnaud-lb
Copy link
Member Author

@janedbal I didn't plan to. Do you have example use cases?

@arnaud-lb arnaud-lb closed this in 14fc50e Mar 27, 2025
@arnaud-lb
Copy link
Member Author

Thanks everyone for the reviews!

@janedbal
Copy link

Do you have example use cases?

Yes. We built a tool that tries to detect "memory leaks" by scanning all global space (static vars, closure uses, ...). One of the few places that is currently not accessible at all are shutdown handlers.

For reference, here is some initial version of that.

@arnaud-lb
Copy link
Member Author

This makes sense, thanks! I'm adding this on my TODO (but if anyone wants to take care of this, feel free).

nicolas-grekas added a commit to symfony/polyfill that referenced this pull request Mar 31, 2025
This PR was squashed before being merged into the 1.x branch.

Discussion
----------

Add `get_*_handler` polyfills

Here is the polyfill of newly implemented `get_error_handler` and `get_exception_handler`.
I have created the default files for PHP 8.5 polyfills.

The tests are taken from php/php-src#17693, but some cannot be completed due to new PHP 8 syntax.

There are some issues with the error handler in the tests, I can't figure out why. If someone can help, that would be great! 😅 This seems to be related to the TestListenerTrait, I think.

[RFC](https://wiki.php.net/rfc/get-error-exception-handler)

Commits
-------

d791faa Add `get_*_handler` polyfills
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants