register_shutdown_function not catch Fatal error:

2019-01-29 02:03发布

问题:

i have this:

  1. i have An HTTACCESS file with directive to prepend a file for config and handle error: (it is mandatory: According to the documentation, this file must be attached before any other php script is executed in order to obtain errors: such as E_PARSE.)

    php_value auto_prepend_file "./server/conferror.php"
    
  2. the content of conferror.php:

    <?php
    declare(strict_types=1);
    ini_set('session.gc_maxlifetime', '0');
    ini_set('session.use_only_cookies', '1');
    ini_set('session.cookie_httponly', '1');
    ini_set('allow_url_fopen', '1');
    ini_set('allow_url_include', '1');
    ini_set('error_reporting', '1');
    ini_set('display_errors', '0');
    error_reporting(E_ALL);
    set_error_handler("ErrorHandler");
    register_shutdown_function("ShutdownHandler");
    function ErrorHandler($error_level, $error_message, $error_file, $error_line, $error_context) {
        $ErrorHandler = "<b>File:</b> " . $error_file . '<br>' .
            "<b>Line :</b> " . $error_line . '<br>' .
            "<b>Desc:</b> <br>" . $error_message . '<br>';
        echo $ErrorHandler;
        exit;
    }
    function ShutdownHandler() {
        $CheckError = error_get_last();
        if ($CheckError != null) {
            $ErrorHandler = "<b>File:</b> " . $CheckError['file'] . '<br>' .
                "<b>Line :</b> " . $CheckError['line'] . '<br>' .
                "<b>Desc:</b> <br>" . $CheckError['message'] . '<br>';
            echo $ErrorHandler;
            exit;
        }
    }
    ?>
    
  3. in my index.php i have this to start work the aplication:

    <?php
        require_once 'class.Main.php';
        $WebAPP = new CORE();
        $WebAPP->Main();
    ?>
    
  4. in Main file i have a test, this code to unset a Static Object and Test Erros Handlers:

    <?php
    class CORE {
        public static $ObjClass;
        public function __construct() {
            self::$ObjClass['data']='data';
        }
        public function __destruct() {
            unset(CORE::$ObjClass);
        }
        public function Main() {
            #not Test on this.
        }
    }
    ?>
    

I have 3 questions:

  1. Why Event handler does not capture the following error?

Fatal error: Uncaught Error: Attempt to unset static property CORE::$ObjClass in C:\xampp\htdocs\dev\t2\class.Main.php:8 Stack trace: #0 [internal function]: CORE->__destruct() #1 {main} thrown in C:\xampp\htdocs\dev\t2\class.Main.php on line 8

Second test:

This code:

<?php
class CORE {
    public function __construct() {
    }
    public function __destruct() {
        prom();
    }
    public function Main() {
        #not Test on this.
    }
}
?>

Generate this error:

Fatal error: Uncaught Error: Call to undefined function prom() in C:\xampp\htdocs\dev\t2\class.Main.php:6 Stack trace: #0 [internal function]: CORE->__destruct() #1 {main} thrown in C:\xampp\htdocs\dev\t2\class.Main.php on line 6

Update:

after much test i see that the error handler work fine with errors in declared function; but this not work in __construct or__destruct function.

回答1:

  1. Why i cant unset static property CORE::$ObjClass or self::$ObjClass?

Good question. I don't see anything in the official documentation of unset() or static properties that mentions this. But obviously you can't.

  1. What is the right way to do it with static property?

You could just set it to NULL or an empty array.

  1. Why Event handler does not capture the following error?

The documentation says:

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.

This error is presumably one of these types. I'm not sure how to tell specifically what its type is.

The shutdown function is being called, but for some reason error_get_last() is returning NULL rather than the information about this error.



回答2:

After doing a lot of searching in the documentation and online.

it is not clear why the error handlers do not work correctly in the __construct or __desctruct; but as a remote idea I am assuming that these two functions are verified even before interpreting the HTTACCESS files or that even though the file is executed the directives: php_value auto_prepend_file is being executed after the two functions __construct and __desctruct are verified, this severely disrupts how handle errors and can lead to implement solutions not as comfortable as the following.

As a first point I had to implement another set that I had not read before or found, in the research I found it:

set_exception_handler ("ExeptionHandler");

and I imagine that I will have to implement others to the extent.

as a second point for this personal development: you should go from using any Method of these __construc and __destruct, and migrate to nesting everything in the declared methods.

Then the script and the structure are as follows:

HTTACCESS Files (Same):

php_value auto_prepend_file "./server/conferror.php"

conferror.php(Update with new set):

<?php
declare(strict_types=1);
ini_set('session.gc_maxlifetime', '0');
ini_set('session.use_only_cookies', '1');
ini_set('session.cookie_httponly', '1');
ini_set('allow_url_fopen', '1');
ini_set('allow_url_include', '1');
ini_set('error_reporting', '1');
ini_set('display_errors', '0');
error_reporting(E_ALL);
register_shutdown_function("ShutdownHandler");
set_error_handler("ErrorHandler");
set_exception_handler("ExeptionHandler");
function ShutdownHandler() {
    $CheckError = error_get_last();
    if ($CheckError != null) {
        $ErrorHandler = "<b>File:</b> " . $CheckError['file'] . '<br>' .
            "<b>Line:</b> " . $CheckError['line'] . '<br>' .
            "<b>Desc:</b> <br>" . $CheckError['message'] . '<br>';
        echo $ErrorHandler;
    }
}
function ErrorHandler($error_level, $error_message, $error_file, $error_line, $error_context) {
    $ErrorHandler = "<b>File:</b> " . $error_file . '<br>' .
        "<b>Line:</b> " . $error_line . '<br>' .
        "<b>Desc:</b> <br>" . $error_message . '<br>';
    echo $ErrorHandler;
}
function ExeptionHandler($e) {
    $ErrorHandler = "<b>File:</b> " . $e->getFile() . '<br>' .
        "<b>Line:</b> " .  $e->getLine() . '<br>' .
        "<b>Desc:</b> <br>" .  $e->getMessage() . '<br>';
    echo $ErrorHandler;
}
?>

index.php (same not changed):

<?php
    require_once 'class.Main.php';
    $WebAPP = new CORE();
    $WebAPP->Main();
?>

Script Main to Test (Update: remove __construct and __destruct from programing structure):

<?php
class CORE {
    public static $ObjClass;
    public function Main() {
        #not Test on this.
        self::$ObjClass['data'] = 'data';
        unset(CORE::$ObjClass);
    }
}?>

For the moment is all that can make with this. i will update it if i find new information in the future.