Bug #70689 [Ver->Csd]: Exception handler does not work as expected.
| From: | laruence@php.net | Date: | Tue, 13 Oct 2015 09:44:40 +0000 |
| Subject: | Bug #70689 [Ver->Csd]: Exception handler does not work as expected. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-196590@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
Updated by: laruence@php.net
Reported by: yajenyak at yandex dot ru
Summary: Exception handler does not work as expected.
-Status: Verified
+Status: Closed
Type: Bug
Package: Scripting Engine problem
Operating System: *
PHP Version: 7.0.0RC4
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a8ae88162fe2ee2f9ca9846ff62c1d4d0d141a6a
Log: Fixed bug #70689 (Exception handler does not work as expected)
Previous Comments:
------------------------------------------------------------------------
[2015-10-12 09:17:24] nikic@php.net
The main problem here is that the return value of http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_execute.c#896
was inverted. Furthermore http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_vm_def.h#4717
does an unconditional HANDLE_EXCEPTION() in the failure case, even though the warning does not
necessarily result in an exception. Should probably issue ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() in
the failure case.
------------------------------------------------------------------------
[2015-10-12 00:54:13] requinix@php.net
https://3v4l.org/haASA
So the problem is that the function gets executed even if there is an exception thrown during the
call.
------------------------------------------------------------------------
[2015-10-12 00:13:21] yajenyak at yandex dot ru
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...
...
------------------------------------------------------------------------
[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.
------------------------------------------------------------------------
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=70689
--
Edit this bug report at https://bugs.php.net/bug.php?id=70689&edit=1