phperror-handlingmonolog

Should the error handler set with set_error_handler terminate the script when a fater error is reported?


Should a handler set with set_error_handler() terminate the script if fatal errors are reported. For instane E_USER_ERROR or will this be handled anyway?

I have a application the registers a handler with monolog but trigger_error( '', E_USER_ERROR ); does not terminate the script.

the handler:

set_error_handler( function ($errno, $errstr, $errfile, $errline) {
    // error was suppressed with the @-operator
    if( 0 === error_reporting() ) {
        return false;
    }
    switch($errno) {
        default:
            LOG->error( "Unknown error type: [$errno] $errstr", [ 'file' => $errfile, '@' => $errline ] );
            break;
        case E_USER_ERROR: // fall through
        case E_ERROR: // fall through
        case E_WARNING: // PHP Warnings are errors
            LOG->error( $errstr, [ 'file' => $errfile, '@' => $errline ] );
            break;
        case E_USER_DEPRECATED:
        case E_DEPRECATED:
            LOG->error( "DEPRECATED $errstr", [ 'file' => $errfile, '@' => $errline ] );
            break;
        case E_USER_WARNING: // fall through
        case E_NOTICE: // PHP Notices are warnings
            LOG->warning( $errstr, [ 'file' => $errfile, '@' => $errline ] );
            break;
        case E_USER_NOTICE:
            LOG->notice( $errstr, [ 'file' => $errfile, '@' => $errline ] );
            break;
    }
    /* Don't execute PHP internal error handler */
    return true;
} );

Solution

  • When you set a custom error handler using set_error_handler(), it allows you to intercept and handle different types of PHP errors. However, the behavior of the script after handling the error depends on how the handler is implemented.

    In your case, your custom error handler does not stop script execution after handling an E_USER_ERROR or similar fatal errors (E_ERROR). This is why the script continues to execute even after a trigger_error('', E_USER_ERROR).

    Solution

    To terminate the script when a fatal error is encountered (like E_USER_ERROR), you need to explicitly terminate the script using exit() or die() inside your custom error handler. Here's how you can modify your handler to terminate the script:

    set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }
    
    switch ($errno) {
        default:
            LOG->error("Unknown error type: [$errno] $errstr", ['file' => $errfile, '@' => $errline]);
            break;
        case E_USER_ERROR: // fall through
        case E_ERROR: // fall through
        case E_WARNING: // PHP Warnings are errors
            LOG->error($errstr, ['file' => $errfile, '@' => $errline]);
            // Default handler not called: terminate the script for fatal errors
            exit(1); 
        case E_USER_DEPRECATED:
        case E_DEPRECATED:
            LOG->error("DEPRECATED $errstr", ['file' => $errfile, '@' => $errline]);
            break;
        case E_USER_WARNING: // fall through
        case E_NOTICE: // PHP Notices are warnings
            LOG->warning($errstr, ['file' => $errfile, '@' => $errline]);
            break;
        case E_USER_NOTICE:
            LOG->notice($errstr, ['file' => $errfile, '@' => $errline]);
            break;
    }
    
    /* Don't execute PHP internal error handler */
    return true; });