How to show Erlang call stack?

前端 未结 4 807
耶瑟儿~
耶瑟儿~ 2021-02-14 18:06

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

相关标签:
4条回答
  • 2021-02-14 18:26

    This might work:

    where_am_i() ->
        try throw(a)
        catch throw:a ->
                erlang:get_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.

    0 讨论(0)
  • 2021-02-14 18:42
    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.

    0 讨论(0)
  • 2021-02-14 18:44

    Here's a simple trick:

    Trace = try throw(42) catch 42 -> erlang:get_stacktrace() end,
    erlang:display(Trace)
    
    0 讨论(0)
  • 2021-02-14 18:45

    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 讨论(0)
提交回复
热议问题