Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to attach erlang dbg to a running process?

How could I attach a debugger to a running erlang process (rabbitmq)? I have the source code of the same rabbit version that's running. I would like to set a breakpoint on a source line, and attach a debugger to the running rabbit instance. I'm not sure if erlang requires debug symbols async_dirty.

In a perfect world, I would like to be able to do that both locally and remotely.

like image 998
polo Avatar asked Feb 10 '23 13:02

polo


1 Answers

From what you're saying, you don't really need to run a debugger. The Erlang VM's concurrency model doesn't fit well with the concept of stop-everything-and-inspect-style debugging.

On the other hand, the VM has great, built-in tracing capabilities. The dbg module is where they are all exposed, but that module's interface is quite difficult to use, especially if you're a beginner. I'd recommend using recon_trace to get a view into what's going on with your process: http://ferd.github.io/recon/recon_trace.html.

If you don't feel like installing recon, start your program from the Erlang shell, and in that shell, type:

%enable tracing capabilities
1> dbg:tracer().  

% Trace Pattern Local-scope 
% (tell the tracer to trace every call in YourModule, even unexported functions).
2> dbg:tpl(YourModule, x). 

% Tell dbg to print calls from all processes calling your module.
3> dbg:p(all,call). 

% Run your traced module
4> YourModule:SomeFun().  

% You should see nice(?) traces of inputs, outputs, and
% exceptions in your shell

Check out the following session, where I fumble around not knowing how to use the queue module:

Eshell V6.3  (abort with ^G)
1> dbg:tracer(), dbg:tpl(queue, x), dbg:p(all, call).
{ok,[{matched,nonode@nohost,26}]}
2> X = queue:new().
(<0.33.0>) call queue:new()
(<0.33.0>) returned from queue:new/0 -> {[],[]}
{[],[]}
3> X = queue:cons(1).
** exception error: undefined function queue:cons/1
4> X = queue:cons(X,1).
(<0.39.0>) call queue:cons({[],[]},1)
(<0.39.0>) call queue:in_r({[],[]},1)
(<0.39.0>) exception_from {queue,in_r,2} {error,badarg}
(<0.39.0>) exception_from {queue,cons,2} {error,badarg}
** exception error: bad argument
     in function  queue:in_r/2
        called as queue:in_r({[],[]},1)
5> X = queue:cons(1,X).
(<0.41.0>) call queue:cons(1,{[],[]})
(<0.41.0>) call queue:in_r(1,{[],[]})
(<0.41.0>) returned from queue:in_r/2 -> {[],[1]}
(<0.41.0>) returned from queue:cons/2 -> {[],[1]}
** exception error: no match of right hand side value {[],[1]}
6> X1 = queue:cons(1,X).
(<0.43.0>) call queue:cons(1,{[],[]})
(<0.43.0>) call queue:in_r(1,{[],[]})
(<0.43.0>) returned from queue:in_r/2 -> {[],[1]}
(<0.43.0>) returned from queue:cons/2 -> {[],[1]}
{[],[1]}

Hope this helps to get you started.

If you want to see how the Erlang wizards do it, watch Mats Cronqvist's talk "Taking the printf out of printf debugging".

like image 73
Simon Zelazny Avatar answered Feb 14 '23 07:02

Simon Zelazny