My end goal is to be able to properly log "FATAL" errors, which are sadly not "seen" by set_error_handler.

Currently, all PHP does is log:

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 65011744 bytes) in blablabla.php on line 27

That kind of log is virtually useless, since it only tells me the very last "point" where it died. That's why I use a custom error handler to log "all" errors with a debug_backtrace(). But since set_error_handler doesn't "get" FATAL errors, I found (on Stack Exchange) an alleged way to handle those errors anyway, by registering a "shutdown function" which checks for the last error, makes a debug_backtrace() and logs that.

Sadly, when I try it, the debug_backtrace() seems to be very limited and does not include all the "steps" at all. Example:

function handle_critical_errors()
{
    $error_data = error_get_last();
    var_dump($error_data);
    var_dump(debug_backtrace());
}

function shutdown_handler_function()
{
    handle_critical_errors();
}

register_shutdown_function('shutdown_handler_function');

function nonbroken_function()
{
    broken_function();
}

function broken_function()
{
    $buffer = '';

    for ($i = 0; $i < 999999999999999; $i++)
        $buffer .= 'this is intended to exhaust all availabile memory because trigger_error doesn\'t let me trigger a fatal error for unknown reasons';
}

nonbroken_function();

When I run this, this is outputted:

array(4) {
  ["type"]=>
  int(1)
  ["message"]=>
  string(83) "Allowed memory size of 134217728 bytes exhausted (tried to allocate 65011744 bytes)"
  ["file"]=>
  string(54) "blablablabla.php"
  ["line"]=>
  int(27)
}
array(2) {
  [0]=>
  array(4) {
    ["file"]=>
    string(54) "blablablabla.php"
    ["line"]=>
    int(12)
    ["function"]=>
    string(22) "handle_critical_errors"
    ["args"]=>
    array(0) {
    }
  }
  [1]=>
  array(2) {
    ["function"]=>
    string(25) "shutdown_handler_function"
    ["args"]=>
    array(0) {
    }
  }
}

There is no mention of broken_function() or nonbroken_function(), even though these were called. I don't get it. Even though it's obvious what is causing the FATAL error in this minimal test/example, this is never or rarely the case in the "real world", where it will just point at a generic line somewhere in my complex system and the only "backtrace" consists of just the shutdown handler function and the error handler function. There is no real "context". I don't understand what I'm doing wrong.

Furthermore, I don't understand the point of error_get_last() to begin with since PHP logs the FATAL error by default anyway, but again, shows no context even if I use the backtrace function.

I've re-read the manual about the debug_backtrace function but it says very little about what a backtrace is. I thought I understood what it is, but apparently, I don't?

Is the "cut-off" backtrace perhaps somehow related to the fact that this is a FATAL error, and this makes even that basic function unable to operate properly? If such this the case, doesn't that mean that it's literally impossible to properly log (and thus debug) FATAL errors without pure guesswork/manual figuring of the code?

0

There are 0 best solutions below