开发者

How to show Erlang call stack?

I need to debug some module in foreign system. The module has public function foo() - how can I know place (module and function name) from which foo() given module was called? I mean stack of calls.

I cannot stop system, all work I can do by reload this module (but with some debug info).

-module(given).
-export(foo/0).

foo() ->开发者_开发技巧
    %% here is my debug - and
    %% i need here(!) known about unknown_module:unknown_foo!
    ok.

---
-module(unknown_module).
..

unknown_foo() ->
    given:foo().  %% see above


Here's a simple trick:

Trace = try throw(42) catch 42 -> erlang:get_stacktrace() end,
erlang:display(Trace)


This might work:

where_am_i() ->
    try throw(a)
    catch throw:a:Stacktrace ->
            Stacktrace
    end.

Except that it doesn't work for tail calls. For example, given these two functions:

foo() ->
    where_am_i().

bar() ->
    X = where_am_i(),
    {ok, X}.

I get these results:

4> foo:foo().
[{foo,where_am_i,0},
 {erl_eval,do_apply,5},
 {shell,exprs,6},
 {shell,eval_exprs,6},
 {shell,eval_loop,3}]
5> foo:bar().
{ok,[{foo,where_am_i,0},
     {foo,bar,0},
     {erl_eval,do_apply,5},
     {shell,exprs,6},
     {shell,eval_exprs,6},
     {shell,eval_loop,3}]}

That is, I can only see bar, since foo's call frame has been left already when where_am_i is called.


io:format("~s~n", [element(2, process_info(self(), backtrace))]).

self() can be replaced by any other pid (rpc:pinfo should even work with remote procs). This helps if you cannot even modify the source or beam.


Here is my code for doing this:

format_stack_entry(S) ->
    {Module,Fun,Arity,[{file,File},{line,Line}]}=S,
    io_lib:format("{~p,~p,~p,[{file,~p},{line,~p]}",[Module,Fun,Arity,File,Line]).
stacktop([Top|_]) ->
    Top.
ancestor(N) ->
    {_,Stacktrace}=erlang:process_info(self(),current_stacktrace),
    ancestor(N+1,Stacktrace).
ancestor(1,S) ->
    format_stack_entry(stacktop(S));
ancestor(N,[_|T]) ->
    ancestor(N-1,T).

info(Format)      -> io:format(lists:concat([ancestor(2),Format,"\r"])).
info(Format,Args) -> io:format(lists:concat([ancestor(2),Format,"\r"]),Args).

Lists is a custom module in the system. Use your foo module instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜