6

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.

3
  • 2
    This was reported as a bug a couple years ago, but then was not reproducible: bugs.php.net/bug.php?id=70188 Commented Jan 1, 2018 at 4:26
  • Tested. Unable to replicate in PHP 7.1 on Win, Ubuntu, docker(ubuntu). Unable to replicate in PHP 5.6 on Win, Ubuntu, docker(ubuntu). Commented Feb 5, 2018 at 21:31
  • 1
    I tried this on phpio.net/s/6v6g, and it seems to not work in any of the PHP versions there either. So see this one: stackoverflow.com/questions/7241834/…. Though that one is about register_shutdown_function, it may be the same. The trace can only start from within where it is being called, which may not be happening in this case. It is more like this: print(""); dump(); array_search('green', Array()); dump(); So in this case, it really is tracing itself since it is not being called from inside anything else. Commented Feb 15, 2018 at 17:43

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.