Erlang стек вызовов - PullRequest
       38

Erlang стек вызовов

9 голосов
/ 12 февраля 2010

мне нужно отладить какой-то модуль во внешней системе, модуль имеет публичную функцию foo () - как узнать место (имя модуля и функции) из какого foo () был вызван данный модуль? Я имею в виду стек вызовов.

PS: я не могу остановить систему, все, что я могу сделать, перезагрузив этот модуль (но с информацией отладки som)

-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

Ответы [ 4 ]

19 голосов
/ 12 февраля 2010

Вот простой трюк:

Trace = try throw(42) catch 42 -> erlang:get_stacktrace() end,
erlang:display(Trace)
2 голосов
/ 12 февраля 2010

Это может сработать:

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

За исключением того, что он не работает для оконечных вызовов. Например, с учетом этих двух функций:

foo() ->
    where_am_i().

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

Я получаю эти результаты:

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}]}

То есть я вижу только bar, так как кадр вызова foo уже оставлен при вызове where_am_i.

1 голос
/ 16 декабря 2015

Вот мой код для этого:

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).

Списки - это пользовательский модуль в системе. Вместо этого используйте свой модуль foo.

1 голос
/ 13 февраля 2010
io:format("~s~n", [element(2, process_info(self(), backtrace))]).

self () можно заменить любым другим pid (rpc: pinfo должен работать даже с удаленными процессорами). Это помогает, если вы даже не можете изменить источник или луч.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...