Bug #70689 [Fbk->Opn]: Exception handler does not work as expected.
| From: | yajenyak at yandex dot ru | Date: | Mon, 12 Oct 2015 00:13:22 +0000 |
| Subject: | Bug #70689 [Fbk->Opn]: Exception handler does not work as expected. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-196535@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=70689&edit=1
ID: 70689
User updated by: yajenyak at yandex dot ru
Reported by: yajenyak at yandex dot ru
Summary: Exception handler does not work as expected.
-Status: Feedback
+Status: Open
Type: Bug
Package: Scripting Engine problem
Operating System: Arch Linux 4.2.2, 64-bit
PHP Version: 7.0.0RC4
Block user comment: N
Private report: N
New Comment:
Thank you for you comment. I able to reproduce the bug, here is a code:
<?php
class MyHandler {
public function handleException(\Throwable $e) {
die('This line WILL NOT be called!');
}
public function handleError($errno, $errstr, $errfile, $errline, $context) {
if ($errno & error_reporting()) {
// This line should cause the MyHandler::handleException() be called
// but the the die() in the $myCallback is executed instead,
// it should not happen!
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}
}
public function shutdown() {
die("\n" . __METHOD__ . ' called');
}
}
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
$myHandler = new MyHandler;
set_error_handler([$myHandler, 'handleError']);
set_exception_handler([$myHandler, 'handleException']);
register_shutdown_function([$myHandler, 'shutdown']);
// ------------------------
// In some method of some class:
class MySomeClass {
public function test() {
$method = 'doSomething';
$res = $this->$method();
}
public function doSomething() {
// ...
$myCallback = function ($name) {
die('This line WILL be executed!');
};
foreach (['a', 'b', 'c'] as $item) {
// ...
try {
// Trigger error - E_WARNING
$res = $myCallback();
} catch (\Throwable $e) {
die('This line WILL NOT be executed');
}
die('This line WILL NOT be executed');
}
}
}
$instance = new MySomeClass();
$instance->doSomething();
-------------------------------------------------------------
Part of the output is:
This line WILL be executed!PHP Fatal error: Uncaught ErrorException: Missing argument 1 for
MySomeClass::{closure}(), called in ... on line 44 and defined...
...
Previous Comments:
------------------------------------------------------------------------
[2015-10-11 12:22:15] requinix@php.net
Really need that repro script because as far as I can tell from that code, it should not repro your
problem. Which is what you said is the case. But it looks like what you've given should be
close?
By the way, there's a bug in your code:
if ($errno && error_reporting()) {
That's a boolean &&. What the expression does is check that $errno != 0 (the expression
was not @-silenced) and that error_reporting() != 0. What you should be doing is checking that the
error_reporting() bitmask has the $errno bit set - using the bitwise &. An easy mistake/typo to
make.
if ($errno & error_reporting()) {
------------------------------------------------------------------------
[2015-10-11 06:05:32] yajenyak at yandex dot ru
Updated OS information.
------------------------------------------------------------------------
[2015-10-11 03:34:02] yajenyak at yandex dot ru
Description:
------------
When the ErrorException is thrown in the error handler registered with set_error_handler() the
exception handler is not called but the next line in the code is executed which not should happend
because the exception handler must be called.
I can't provide exact chunk of the code because the error is not reproducable without context,
but the code that I will provide causes the bug happen in the context.
This bug may be related with the https://bugs.php.net/bug.php?id=70210 but I
don't have enough knowledge of the PHP internals for now to make conclusions.
Test script:
---------------
// This error code doesn't reproduce the error without context code, but it shows when the bug
happens:
class MyHandler {
public function handleException(\Throwable $e) {
die('This line WILL NOT be called!');
}
public function handleError($errno, $errstr, $errfile, $errline, $context) {
if ($errno && error_reporting()) {
// This line should cause the MyHandler::handleException() be called
// but the the die() in the $myCallback is executed instead,
// it should not happen!
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}
}
public function handleError($errno, $errstr, $errfile, $errline, $context) {
die('called');
}
}
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
$myHandler = new MyHandler;
set_error_handler([$myHandler, 'handleError']);
set_exception_handler([$myHandler, 'handleException']);
register_shutdown_function([$myHandler, 'shutdown']);
// ------------------------
// In some method of some class:
class MySomeClass {
// ...
public function doSomething() {
// ...
$myCallback = function ($name) {
die('This line WILL be executed!');
};
foreach ($collection as $item) {
// ...
try {
// Trigger error - E_WARNING
$res = $myCallback();
} catch (\Throwable $e) {
die('This line WILL NOT be executed');
}
die('This line WILL NOT be executed');
// ...
// ...
}
Expected result:
----------------
Calling of the MyHandler::handleException()
Actual result:
--------------
The die() function is called here:
$myCallback = function ($name) {
die('This line WILL be executed!');
};
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=70689&edit=1