Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP debug_backtrace() called by register_tick_function() does not return the full stack

I want to use register_tick_function() to hook the following calls and print their stack trace with debug_backtrace().

If I run the following code.

<?php

function dump() {
  // Replace this with var_dump(debug_backtrace()); to print the entire trace.
  foreach (debug_backtrace() as $trace)
    echo("Function ${trace['function']}() has been called" . PHP_EOL);
}

declare(ticks = 1);
register_tick_function('dump');

print("");
array_search('green', Array());

It prints only the dump() function.

Function dump() has been called
Function dump() has been called
Function dump() has been called

Why I'm not seeing print() and array_search() trace data? It's like the stack has been reset before invoking dump(). I'm also pretty sure it worked properly in the past.

like image 563
Emilio Avatar asked Dec 31 '17 11:12

Emilio


1 Answers

You are misunderstanding what the backtrace is, this stack is not a list of functions that PHP executed before reaching a certain line of code, but rather the list of nested functions that justify PHP's interpreter to be at a specific line of code.

The first element will always be the function you are currently in, the next will be the function that called that function and so on. If a function returns, it is no longer in the stack.

class Foo {
    public static function bar() {
        return self::say();
    }

    public static function say() {
        return debug_backtrace();
    }
}

var_dump(Foo::say());
//[0] => say()

var_dump(Foo::bar());
//[0] => say();
//[1] => bar();

//Note that this behaviour work the same for require(), include() and eval()

require_once('test.php');

//test.php:
var_dump(debug_backtrace());
//[0] => require_once()

As PHP interprets your script, it navigates your functions, adding and removing from the current stack. The stack of the backtrace is not the place were PHP logs what functions were called in chronological order.

For the latter, this is a solution I found: Get a called functions list in PHP

like image 103
janzim Avatar answered Oct 02 '22 11:10

janzim