Rexbug: get arguments instead of arity in :retn trace-messages

TIL that I can hook my own print functions into Rexbug:

iex(1)> Rexbug.start("Map.get/_ :: return", [print_fun: fn msg -> IO.inspect(msg) end])                                                      
{111, 2}
iex(2)> Map.get(%{a: 1}, :a)
1
{:call, {{Map, :get, [%{a: 1}, :a]}, ""}, ...}
{:call, {{Map, :get, [%{a: 1}, :a, nil]}, ""}, ...}
{:retn, {{Map, :get, 3}, 1}, ...}
{:retn, {{Map, :get, 2}, 1}, ...}

Is there a way to get the arguments for :retn also, as you see I only get the arity.
But I can’t match the :retn with their :call messages without the arguments.

I’d like to visualize a tree-traversal and the plan is to indent the steps using the alternative print_fun/2 with acc. So use acc to keep track of the level, indenting for nodes, not indenting for leaves. But to unindent I need to know what I’m returning from.

Well, you cannot return from any other function that the one you currently are in (I assume that you trace single process), so you can have simple list of :calls and pop the head to get the arguments for current function.

1 Like

Thanks for your help. I’m not sure I fully understand, I’ll look into that when I got the time.

In short if you trace single process, then when you have list of calls like:

  1. Call A
  2. Call B
  3. Call C

Then the return list must be in the reverse order, as function cannot return before it’s parent will return.

2 Likes

For the sake of completeness: this is true when TCO (tail call optimization) is not active. See the match spec docs, under the return_trace option.

Redbug uses this option, so indeed there should be a return message for every call. But be careful not to trace functions that are intended to loop indefinitely, as this could lead to memory exhaustion.

When tracing with lower level functions (e.g. the :dbg module or :erlang.trace_pattern/3), the return_to flag can be used to trace calls and returns without impacting the TCO behavior, so it is arguably safer to use in production. But it is harder (or impossible) to reliably correlate the return to a prior call.

3 Likes