2010-02-12 24 views
8

necesito depurar algún módulo en un sistema externo, módulo tiene función pública foo() - ¿cómo puedo saber el lugar (módulo y nombre de función) desde el cual se llamó el módulo dado foo()? Me refiero a la pila de llamadas.erlang call stack

PS: No puedo parada del sistema, todo el trabajo que puedo hacer por recarga de este módulo (pero con som información de depuración)

-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 
+0

Modifiqué mi ejemplo, por favor comente – vinnitu

+1

Tenga en cuenta que en un caso como el ejemplo anterior, la llamada a given: foo() es una llamada final - esto significa que no quedará rastro de ella en la pila (por definición). Si necesita hacer este tipo de depuración, debe aprender sobre el rastreo en Erlang. – RichardC

Respuesta

17

He aquí un truco simple:

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

Esto podría funcionar:

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

Excepto que no funciona para las llamadas finales. Por ejemplo, teniendo en cuenta estas dos funciones:

foo() -> 
    where_am_i(). 

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

que recibo estos resultados:

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

Es decir, que sólo se puede ver bar, ya foo 's marco de llamada se ha dejado ya en el momento where_am_i se llama .

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

auto() puede ser sustituido por cualquier otro PID (RPC: pinfo siquiera debería trabajar con procsos remotas). Esto ayuda si ni siquiera puedes modificar la fuente o haz.

0

Aquí está mi código para hacer esto:

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

listas es un módulo personalizado en el sistema. Use su módulo foo en su lugar.