Подтвердить что ты не робот

Debug_backtrace() от зарегистрированной функции выключения в PHP

Во время поиска ответа на этот вопрос я обнаружил, что debug_backtrace() не отслеживает функцию, зарегистрированную на register_shutdown_function(), при вызове из нее.

Это было упомянуто в этот комментарий для register_shutdown_function() в документах PHP, указав:

У вас может возникнуть идея вызвать debug_backtrace или debug_print_backtrace изнутри функции выключения, чтобы отслеживать, где произошла фатальная ошибка. К сожалению, эти функции не будут работать внутри функции выключения.

Объяснение с более подробной информацией, комментарии к этому ответу:

Не работает. Функция выключения происходит после того, как стек отключился. Нет данных о стеке для сброса.

Есть ли способ обойти это, заставляя PHP удерживать трассировку стека до тех пор, пока процесс не завершится вообще, или мы не должны принимать его как заданный из-за внутренних функций PHP?

4b9b3361

Ответ 1

Есть ли способ обойти это, заставляя PHP удерживать трассировку стека

Это довольно бессмысленно, когда вызывается зарегистрированная функция, все ваши определенные функции вернулись или были удалены из стека.

Если вам нужно знать, где выходил ваш код, вам необходимо настроить код.

Ответ 2

Это очень дорогое решение. Я никогда не использовал register_tick_function() или tick, и я "Не уверен, работает ли он так, как ожидалось".

declare(ticks=1);

function tick_handler() {
    global $backtrace;
    $backtrace = debug_backtrace();
}
register_tick_function('tick_handler');



function shutdown() {
    global $backtrace;
    // do check if $backtrace contains a fatal error...
    var_dump($backtrace);
}
register_shutdown_function('shutdown');

Ответ 3

По моему опыту, функция останова начинается с чистого стека и не имеет доступа к "исходному" стеку (поскольку он больше не существует в этой точке).

К сожалению, нет способа сохранить исходный стек.

Ответ 4

В XDebug расширение xdebug_get_function_stack().

Этот файл похож на внутренний PHP debug_backtrace(), но сохраняет трассировку даже в обработчике выключения.

Вы не получите точную точку выхода, но только последняя выполненная функция до выключения (вызвана вызовом die()/exit() или ошибкой).

Это, конечно, подходит только для среды разработки.

Ответ 5

Внутри вашей зарегистрированной функции выключения вы можете получить обратный след с помощью функции error_get_last. У меня работает в PHP7.