Bug #63206 [Com]: restore_error_handler does not restore previous errors mask
| From: | not-implemented at mark-plomer dot de | Date: | Mon, 24 Feb 2020 21:26:15 +0000 |
| Subject: | Bug #63206 [Com]: restore_error_handler does not restore previous errors mask | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-225714@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=63206&edit=1
ID: 63206
Comment by: not-implemented at mark-plomer dot de
Reported by: gwarnants at gmail dot com
Summary: restore_error_handler does not restore previous
errors mask
Status: Open
Type: Bug
Package: *General Issues
Operating System: Windows XP
PHP Version: 5.4.7
Block user comment: N
Private report: N
New Comment:
I created a draft-pull-request for this issue:
https://github.com/php/php-src/pull/5206
@nikic: Independently from your proposal to not remove the error-handler while error-handling (which
also makes sense), I think we always have to push the "empty" handler to the stack to have
a consistent behaviour.
This would fix this issue, but I'm not fully aware of the consequences. What do you think?
Previous Comments:
------------------------------------------------------------------------
[2020-02-24 18:15:34] not-implemented at mark-plomer dot de
The problem is not only about the "error mask". It affects the error-handler itself.
Calling set/restore_error_handler() inside the error-handler "corrupts" the
"old-error-handler" stack, when there are already >= 2 registered handlers. For future
errors, the wrong error-handler is called.
I run into this problem while debugging this issue in Sentry: https://github.com/getsentry/sentry-php/issues/976
Problem still exists in 7.4.3 (and probably "master").
Simpler test-script which also shows the use-case:
Test script:
------------
set_error_handler(function() {
echo 'First handler' . PHP_EOL;
});
set_error_handler(function() {
echo 'Second handler' . PHP_EOL;
set_error_handler(function() {
echo 'Internal handler' . PHP_EOL;
});
$triggerInternalNotice++; // warnings while handling the error should go into internal handler
restore_error_handler();
});
$triggerNotice1++;
$triggerNotice2++;
Expected result:
----------------
Second handler
Internal handler
Second handler
Internal handler
Actual result:
--------------
Second handler
Internal handler
First handler
------------------------------------------------------------------------
[2017-12-28 18:07:19] nikic@php.net
Generally restore_error_handler() does restore the mask as well. What happens here is that while the
error handler is called, the error handler is temporarily removed to prevent recursion. The inner
set_error_handler() call then thinks that there is no error handler registered and does not save the
mask.
Ideally we would not temporarily remove the error handler and instead track that it is currently
running in a different way.
------------------------------------------------------------------------
[2016-06-03 14:31:34] a at ustimen dot co
Sorry, my bad -- test script was not robust.
Currently it repeats at PHP from 5.2 to nightly (7.x).
Only under hhvm not repeats.
https://travis-ci.org/garex/php-error-handler-bug/builds/135038478
------------------------------------------------------------------------
[2016-06-03 14:06:57] a at ustimen dot co
Currently repeats at 5.4, 5.5 and 5.6
Seems fixed in 7.0, hhvm and nightly.
https://travis-ci.org/garex/php-error-handler-bug
------------------------------------------------------------------------
[2016-01-14 02:38:31] hujuice at inserviblie dot org
Same here for PHP 5.6.14 on Linux
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=63206
--
Edit this bug report at https://bugs.php.net/bug.php?id=63206&edit=1