PHP errors do not provide backtraces, which can make it difficult to ascertain their underlying cause. Enabling backtraces for fatal errors will provide vital information to developers debugging production applications.
Take, for example, a recursive infinite loop:
<?php set_time_limit(1); function recurse() { usleep(100000); recurse(); } recurse();
Currently, this results in the following error:
Fatal error: Maximum execution time of 1 second exceeded in example.php on line 7
While the above code is an obvious infinite loop, in large production codebases it may not be as straightforward. If this proposal is accepted, the error could instead look like:
Fatal error: Maximum execution time of 1 second exceeded in example.php on line 6 Stack trace: #0 example.php(6): usleep(100000) #1 example.php(7): recurse() #2 example.php(7): recurse() #3 example.php(7): recurse() #4 example.php(7): recurse() #5 example.php(7): recurse() #6 example.php(7): recurse() #7 example.php(7): recurse() #8 example.php(7): recurse() #9 example.php(7): recurse() #10 example.php(10): recurse() #11 {main}
Seeing this backtrace makes it far more clear that something is amiss with the recursion in this function, without looking at the source code.
Add a fatal_error_backtraces
INI setting, which potentially defaults to “1”.
When enabled, PHP will generate backtraces for errors with an error level matching E_FATAL_ERRORS. Generated backtraces will respect the existing setting for zend.exception_ignore_args
, and parameters marked with the SensitiveParameter
attribute.
error_get_last
will return the backtrace in the array under the trace
key, if it's available. As PHP will only generate backtraces for fatal errors, this will only be available in post-shutdown code, such as callbacks registered via register_shutdown_function
.
Backtraces that contain arguments will increment the refcount for those arguments, which means they will stay alive until the backtrace is destroyed. Since error_get_last
will contain the backtrace for the most recent error, application developers may be surprised by objects lasting longer than they would expect - either until they called error_clear_last
or caused another error.
By limiting this feature to only E_FATAL_ERRORS
, we've also limited this side effect to abnormal situations only. PHP will only execute shutdown handlers after encountering a fatal error, and developers writing shutdown handling code should expect that the application is in an unusual or unreliable state.
In addition, modern PHP applications tend to promote PHP warnings and notices to exceptions via set_error_handler
, which then provides a backtrace via the Error
object. It is only E_FATAL_ERRORS
which are not possible to generate traces for, since they cannot be handled in application code.
Next PHP minor release.
There will be a new Zend global, error_backtrace
, containing the backtrace of the most recent fatal error.
None.
None.
None.
fatal_error_backtraces
— Enable backtraces for errors matching E_FATAL_ERRORS
.
This vote requires a ⅔ majority:
This vote will require a simple majority:
This vote determines if we need to update all phpt
tests in the php-src
repo that feature fatal errors. It depends on the default value, and will require a simple majority:
zend_error_cb
signature to take a backtrace as a nullable argument, instead of storing the backtrace in a Zend global. Unfortunately we would still need to store the backtrace as a global for error_get_last
, and so while modifying the signature is attractive from a correctness standpoint, it is likely not worth making as a breaking change. We could consider it for PHP 9.0, however.