php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60211 register_shutdown_function() not called in combination with set_error_handler()
Submitted: 2011-11-03 13:10 UTC Modified: 2014-04-14 13:27 UTC
Votes:7
Avg. Score:4.6 ± 0.7
Reproduced:7 of 7 (100.0%)
Same Version:2 (28.6%)
Same OS:4 (57.1%)
From: hinikato at gmail dot com Assigned: tyrael (profile)
Status: Closed Package: Class/Object related
PHP Version: 5.3.8 OS: Windows 7 x64
Private report: No CVE-ID: None
 [2011-11-03 13:10 UTC] hinikato at gmail dot com
Description:
------------
My PHP version is: PHP Version 5.3.8-ZS5.5.0, but this bug exist in the Linux environment also. Checked in Debian with PHP 5.3.8.

In the set_error_handler() documentation we have the following quote:
"The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called."

According this quote the bug should not occur if specified error types
will not be raised in the file where set_error_handler() is called.
Let's try to implement such condition.



Test script:
---------------
-- set_error_handler.php --
<?php
$foo = new \Foo\MyErrorHandler();
set_error_handler(array($foo, 'errorHandler'));  // we call the set_error_handler() in the other file.
set_exception_handler(array($foo, 'exceptionHandler'));
register_shutdown_function(array($foo, 'fatalErrorHandler'));
?>
-- end of set_error_handler.php --
-- bug --
namespace Foo;

class MyErrorHandler {
  function errorHandler() {
    echo __METHOD__ . "\n";
    throw new \Exception('test');
  }

  function exceptionHandler() {
    echo __METHOD__ . "\n";  // should be called!
  }

  function fatalErrorHandler() {
    echo __METHOD__ . "\n";  // should be called!
  }
}
require_once __DIR__ . '/set_error_handler.php';
require_once __DIR__ . '/not_existing_file.php'; // file should not exist
die();
-- end of bug --


Expected result:
----------------
Foo\MyErrorHandler::errorHandler
Foo\MyErrorHandler::exceptionHandler
Foo\MyErrorHandler::fatalErrorHandler  // should be called at least!

Fatal error:  main() [function.require]: Failed opening required 'X:\home\localhost\www/not_existing_file.php' (include_path='D:\system\home\projects\myak\www\includes') in X:\home\localhost\www\test.php on line 28


Actual result:
--------------
Foo\MyErrorHandler::errorHandler

Fatal error:  main() [function.require]: Failed opening required 'X:\home\localhost\www/not_existing_file.php' (include_path='D:\system\home\projects\myak\www\includes') in X:\home\localhost\www\test.php on line 28


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-11-03 13:26 UTC] hinikato at gmail dot com
Please note that error handler will be called because the require_once triggers the E_WARNING first, but shutdown function and exception handler will not be called at all.

This bug prevents from writing the following code also, because exceptions is not determined for some reason:
try {
  require_once __DIR__ . '/not_existing_file.php'; // file should not exist
} catch (\Exception $e) {
  echo $e->getMessage();  // will not be called!
}

And this bug prevents from logging fatal errors in our shutdown function if we log them in it.
 [2011-11-03 23:22 UTC] hinikato at gmail dot com
Changed package for the bug description.
 [2011-11-03 23:22 UTC] hinikato at gmail dot com
-Package: Scripting Engine problem +Package: Class/Object related
 [2011-12-06 07:02 UTC] mister dot frb at gmail dot com
Same problem here on PHP 5.2.6-1+lenny13

I could isolate a few interesting things.

the bug seems to depend on the error value. set_error_handler('exceptionsHandler', xx ) where xx < 64 (E_COMPILE_ERROR) and the error handler will be called (don't know why though, ...). The shutdown function is called anyway, but always after the custom error handler.

i don't why it happens, as hinikato said, the documentation says :
"The following error types cannot be handled with a user defined function: [...] E_COMPILE_ERROR [...]"

I can understand why no exception can be raised in the error handler though. I f we are already in a 'shutting down' state, exceptions cannot be raised.

also, somehow related, i tried to reproduce the bug with a different error :
$undefinedvar->method();

when trying to call a method on a undefined object, 2 errors are raised : a notice for the undefined var and a fatal error for calling a method on a non object. If your error handler treats E_NOTICE, it will be called but won't be able to raise an exception in time. the shutdown function will be called and your script stopped. I think there is room for improvement here. Either the error handler should be called, or the shutdown function, but not both of them, especially if the error handler has broken functionality like the incapacity to raise an exception.
 [2014-04-14 11:10 UTC] tyrael@php.net
-Status: Open +Status: Feedback
 [2014-04-14 11:10 UTC] tyrael@php.net
can you reproduce this with php 5.4?
I think this is a duplicate of https://bugs.php.net/bug.php?id=61767 and thus it should be fixed now.
 [2014-04-14 13:27 UTC] tyrael@php.net
-Status: Feedback +Status: Closed -Assigned To: +Assigned To: tyrael
 [2014-04-14 13:27 UTC] tyrael@php.net
Thank you for your bug report. This issue has already been fixed
in the latest released version of PHP, which you can download at 
http://www.php.net/downloads.php

seems to be fixed, the output indeed contains the 'Foo\MyErrorHandler::fatalErrorHandler' line:

Foo\MyErrorHandler::errorHandler

Warning: Uncaught exception 'Exception' with message 'test' in /Users/tyrael/checkouts/php-src.git/bug.php:7
Stack trace:
#0 /Users/tyrael/checkouts/php-src.git/bug.php(19): Foo\MyErrorHandler->errorHandler(2, 'require_once(/U...', '/Users/tyrael/c...', 19, Array)
#1 /Users/tyrael/checkouts/php-src.git/bug.php(19): require_once()
#2 {main}
  thrown in /Users/tyrael/checkouts/php-src.git/bug.php on line 7

Fatal error: main(): Failed opening required '/Users/tyrael/checkouts/php-src.git/not_existing_file.php' (include_path='.:') in /Users/tyrael/checkouts/php-src.git/bug.php on line 19
Foo\MyErrorHandler::fatalErrorHandler
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Apr 14 17:01:28 2024 UTC