<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css"> <title>Erlang -- dbg</title> </head> <body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript"> <!-- function getWinHeight() { var myHeight = 0; if( typeof( window.innerHeight ) == 'number' ) { //Non-IE myHeight = window.innerHeight; } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode' myHeight = document.documentElement.clientHeight; } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible myHeight = document.body.clientHeight; } return myHeight; } function setscrollpos() { var objf=document.getElementById('loadscrollpos'); document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; } function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', setscrollpos); //--></script><div id="leftnav"><div class="innertube"> <img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/runtime_tools-1.8.3.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>Runtime_Tools</strong><br><strong>Reference Manual</strong><br><small>Version 1.8.3</small></p> <br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Table of Contents</strong></small></p> <ul class="flipMenu"> <li title="runtime_tools (App)"><a href="runtime_tools_app.html">runtime_tools (App) </a></li> <li id="loadscrollpos" title="dbg " expanded="true">dbg<ul> <li><a href="dbg.html"> Top of manual page </a></li> <li title="fun2ms-1"><a href="dbg.html#fun2ms-1">fun2ms/1</a></li> <li title="h-0"><a href="dbg.html#h-0">h/0</a></li> <li title="h-1"><a href="dbg.html#h-1">h/1</a></li> <li title="p-1"><a href="dbg.html#p-1">p/1</a></li> <li title="p-2"><a href="dbg.html#p-2">p/2</a></li> <li title="c-3"><a href="dbg.html#c-3">c/3</a></li> <li title="c-4"><a href="dbg.html#c-4">c/4</a></li> <li title="i-0"><a href="dbg.html#i-0">i/0</a></li> <li title="tp-2"><a href="dbg.html#tp-2">tp/2</a></li> <li title="tp-3"><a href="dbg.html#tp-3">tp/3</a></li> <li title="tp-4"><a href="dbg.html#tp-4">tp/4</a></li> <li title="tp-2"><a href="dbg.html#tp-2">tp/2</a></li> <li title="tpl-2"><a href="dbg.html#tpl-2">tpl/2</a></li> <li title="tpl-3"><a href="dbg.html#tpl-3">tpl/3</a></li> <li title="tpl-4"><a href="dbg.html#tpl-4">tpl/4</a></li> <li title="tpl-2"><a href="dbg.html#tpl-2">tpl/2</a></li> <li title="ctp-0"><a href="dbg.html#ctp-0">ctp/0</a></li> <li title="ctp-1"><a href="dbg.html#ctp-1">ctp/1</a></li> <li title="ctp-2"><a href="dbg.html#ctp-2">ctp/2</a></li> <li title="ctp-3"><a href="dbg.html#ctp-3">ctp/3</a></li> <li title="ctp-1"><a href="dbg.html#ctp-1">ctp/1</a></li> <li title="ctpl-0"><a href="dbg.html#ctpl-0">ctpl/0</a></li> <li title="ctpl-1"><a href="dbg.html#ctpl-1">ctpl/1</a></li> <li title="ctpl-2"><a href="dbg.html#ctpl-2">ctpl/2</a></li> <li title="ctpl-3"><a href="dbg.html#ctpl-3">ctpl/3</a></li> <li title="ctpl-1"><a href="dbg.html#ctpl-1">ctpl/1</a></li> <li title="ctpg-0"><a href="dbg.html#ctpg-0">ctpg/0</a></li> <li title="ctpg-1"><a href="dbg.html#ctpg-1">ctpg/1</a></li> <li title="ctpg-2"><a href="dbg.html#ctpg-2">ctpg/2</a></li> <li title="ctpg-3"><a href="dbg.html#ctpg-3">ctpg/3</a></li> <li title="ctpg-1"><a href="dbg.html#ctpg-1">ctpg/1</a></li> <li title="ltp-0"><a href="dbg.html#ltp-0">ltp/0</a></li> <li title="dtp-0"><a href="dbg.html#dtp-0">dtp/0</a></li> <li title="dtp-1"><a href="dbg.html#dtp-1">dtp/1</a></li> <li title="wtp-1"><a href="dbg.html#wtp-1">wtp/1</a></li> <li title="rtp-1"><a href="dbg.html#rtp-1">rtp/1</a></li> <li title="n-1"><a href="dbg.html#n-1">n/1</a></li> <li title="cn-1"><a href="dbg.html#cn-1">cn/1</a></li> <li title="ln-0"><a href="dbg.html#ln-0">ln/0</a></li> <li title="tracer-0"><a href="dbg.html#tracer-0">tracer/0</a></li> <li title="tracer-2"><a href="dbg.html#tracer-2">tracer/2</a></li> <li title="tracer-3"><a href="dbg.html#tracer-3">tracer/3</a></li> <li title="trace_port-2"><a href="dbg.html#trace_port-2">trace_port/2</a></li> <li title="flush_trace_port-0"><a href="dbg.html#flush_trace_port-0">flush_trace_port/0</a></li> <li title="flush_trace_port-1"><a href="dbg.html#flush_trace_port-1">flush_trace_port/1</a></li> <li title="trace_port_control-1"><a href="dbg.html#trace_port_control-1">trace_port_control/1</a></li> <li title="trace_port_control-2"><a href="dbg.html#trace_port_control-2">trace_port_control/2</a></li> <li title="trace_client-2"><a href="dbg.html#trace_client-2">trace_client/2</a></li> <li title="trace_client-3"><a href="dbg.html#trace_client-3">trace_client/3</a></li> <li title="stop_trace_client-1"><a href="dbg.html#stop_trace_client-1">stop_trace_client/1</a></li> <li title="get_tracer-0"><a href="dbg.html#get_tracer-0">get_tracer/0</a></li> <li title="get_tracer-1"><a href="dbg.html#get_tracer-1">get_tracer/1</a></li> <li title="stop-0"><a href="dbg.html#stop-0">stop/0</a></li> <li title="stop_clear-0"><a href="dbg.html#stop_clear-0">stop_clear/0</a></li> </ul> </li> <li id="no" title="erts_alloc_config " expanded="false">erts_alloc_config<ul> <li><a href="erts_alloc_config.html"> Top of manual page </a></li> <li title="save_scenario-0"><a href="erts_alloc_config.html#save_scenario-0">save_scenario/0</a></li> <li title="make_config-0"><a href="erts_alloc_config.html#make_config-0">make_config/0</a></li> <li title="make_config-1"><a href="erts_alloc_config.html#make_config-1">make_config/1</a></li> <li title="stop-0"><a href="erts_alloc_config.html#stop-0">stop/0</a></li> </ul> </li> </ul> </div></div> <div id="content"> <div class="innertube"> <!-- refpage --><center><h1>dbg</h1></center> <h3>MODULE</h3> <div class="REFBODY">dbg</div> <h3>MODULE SUMMARY</h3> <div class="REFBODY">The Text Based Trace Facility</div> <h3>DESCRIPTION</h3> <div class="REFBODY"><p> <p>This module implements a text based interface to the <span class="code">trace/3</span> and the <span class="code">trace_pattern/2</span> BIFs. It makes it possible to trace functions, processes and messages on text based terminals. It can be used instead of, or as complement to, the <span class="code">pman</span> module. </p> <p>For some examples of how to use <span class="code">dbg</span> from the Erlang shell, see the <span class="bold_code"><a href="#simple_example">simple example</a></span> section. </p> <p>The utilities are also suitable to use in system testing on large systems, where other tools have too much impact on the system performance. Some primitive support for sequential tracing is also included, see the <span class="bold_code"><a href="#advanced">advanced topics</a></span> section. </p> </p></div> <h3>EXPORTS</h3> <p><a name="fun2ms-1"><span class="bold_code">fun2ms(LiteralFun) -> MatchSpec</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">LiteralFun = fun() literal</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchSpec = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>Pseudo function that by means of a <span class="code">parse_transform</span> translates the <strong>literal</strong><span class="code">fun()</span> typed as parameter in the function call to a match specification as described in the <span class="code">match_spec</span> manual of <span class="code">ERTS</span> users guide. (with literal I mean that the <span class="code">fun()</span> needs to textually be written as the parameter of the function, it cannot be held in a variable which in turn is passed to the function). </p> <p>The parse transform is implemented in the module <span class="code">ms_transform</span> and the source <strong>must</strong> include the file <span class="code">ms_transform.hrl</span> in STDLIB for this pseudo function to work. Failing to include the hrl file in the source will result in a runtime error, not a compile time ditto. The include file is easiest included by adding the line <span class="code">-include_lib("stdlib/include/ms_transform.hrl").</span> to the source file.</p> <p>The <span class="code">fun()</span> is very restricted, it can take only a single parameter (the parameter list to match), a sole variable or a list. It needs to use the <span class="code">is_</span>XXX guard tests and one cannot use language constructs that have no representation in a match_spec (like <span class="code">if</span>, <span class="code">case</span>, <span class="code">receive</span> etc). The return value from the fun will be the return value of the resulting match_spec.</p> <p>Example:</p> <div class="example"><pre> 1> <span class="bold_code">dbg:fun2ms(fun([M,N]) when N > 3 -> return_trace() end).</span> [{['$1','$2'],[{'>','$2',3}],[{return_trace}]}]</pre></div> <p>Variables from the environment can be imported, so that this works:</p> <div class="example"><pre> 2> <span class="bold_code">X=3.</span> 3 3> <span class="bold_code">dbg:fun2ms(fun([M,N]) when N > X -> return_trace() end).</span> [{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]</pre></div> <p>The imported variables will be replaced by match_spec <span class="code">const</span> expressions, which is consistent with the static scoping for Erlang <span class="code">fun()</span>s. Local or global function calls can not be in the guard or body of the fun however. Calls to builtin match_spec functions of course is allowed:</p> <div class="example"><pre> 4> <span class="bold_code">dbg:fun2ms(fun([M,N]) when N > X, is_atomm(M) -> return_trace() end).</span> Error: fun containing local erlang function calls ('is_atomm' called in guard) cannot be translated into match_spec {error,transform_error} 5> <span class="bold_code">dbg:fun2ms(fun([M,N]) when N > X, is_atom(M) -> return_trace() end).</span> [{['$1','$2'],[{'>','$2',{const,3}},{is_atom,'$1'}],[{return_trace}]}]</pre></div> <p>As you can see by the example, the function can be called from the shell too. The <span class="code">fun()</span> needs to be literally in the call when used from the shell as well. Other means than the parse_transform are used in the shell case, but more or less the same restrictions apply (the exception being records, as they are not handled by the shell).</p> <div class="warning"> <div class="label">Warning</div> <div class="content"><p> <p>If the parse_transform is not applied to a module which calls this pseudo function, the call will fail in runtime (with a <span class="code">badarg</span>). The module <span class="code">dbg</span> actually exports a function with this name, but it should never really be called except for when using the function in the shell. If the <span class="code">parse_transform</span> is properly applied by including the <span class="code">ms_transform.hrl</span> header file, compiled code will never call the function, but the function call is replaced by a literal match_spec.</p> </p></div> </div> <p>More information is provided by the <span class="code">ms_transform</span> manual page in STDLIB.</p> </p></div> <p><a name="h-0"><span class="bold_code">h() -> ok </span></a><br></p> <div class="REFBODY"><p> <p>Gives a list of items for brief online help.</p> </p></div> <p><a name="h-1"><span class="bold_code">h(Item) -> ok </span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Item = atom()</span><br> </div> </div> <div class="REFBODY"><p> <p>Gives a brief help text for functions in the dbg module. The available items can be listed with <span class="code">dbg:h/0</span></p> </p></div> <p><a name="p-1"><span class="bold_code">p(Item) -> {ok, MatchDesc} | {error, term()} </span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">p(Item, [m])</span>.</p> </p></div> <p><a name="p-2"><span class="bold_code">p(Item, Flags) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">MatchDesc = [MatchNum]</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">RPCError = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>Traces <span class="code">Item</span> in accordance to the value specified by <span class="code">Flags</span>. The variation of <span class="code">Item</span> is listed below:</p> <ul> <li>If the <span class="code">Item</span> is a <span class="code">pid()</span>, the corresponding process is traced. The process may be a remote process (on another Erlang node). The node must be in the list of traced nodes (<span class="bold_code"><a href="#n">see</a></span><span class="code">n/1</span> and <span class="code">tracer/0/2/3</span>).</li> <li>If the <span class="code">Item</span> is the atom <span class="code">all</span>, all processes in the system as well as all processes created hereafter are to be traced. This also affects all nodes added with the <span class="code">n/1</span> or <span class="code">tracer/0/2/3</span> function.</li> <li>If the <span class="code">Item</span> is the atom <span class="code">new</span>, no currently existing processes are affected, but every process created after the call is.This also affects all nodes added with the <span class="code">n/1</span> or <span class="code">tracer/0/2/3</span> function.</li> <li>If the <span class="code">Item</span> is the atom <span class="code">existing</span>, all existing processes are traced, but new processes will not be affected.This also affects all nodes added with the <span class="code">n/1</span> or <span class="code">tracer/0/2/3</span> function.</li> <li>If the <span class="code">Item</span> is an atom other than <span class="code">all</span>, <span class="code">new</span> or <span class="code">existing</span>, the process with the corresponding registered name is traced.The process may be a remote process (on another Erlang node). The node must be added with the <span class="code">n/1</span> or <span class="code">tracer/0/2/3</span> function.</li> <li>If the <span class="code">Item</span> is an integer, the process <span class="code"><0.Item.0></span> is traced.</li> <li>If the <span class="code">Item</span> is a tuple <span class="code">{X, Y, Z}</span>, the process <span class="code"><X.Y.Z></span> is traced. </li> <li>If the <span class="code">Item</span> is a string "<X.Y.Z>" as returned from <span class="code">pid_to_list/1</span>, the process <span class="code"><X.Y.Z></span> is traced. </li> </ul> <p><span class="code">Flags</span> can be a single atom, or a list of flags. The available flags are: </p> <dl> <dt><strong><span class="code">s (send)</span></strong></dt> <dd> <p>Traces the messages the process sends.</p> </dd> <dt><strong><span class="code">r (receive)</span></strong></dt> <dd> <p>Traces the messages the process receives.</p> </dd> <dt><strong><span class="code">m (messages)</span></strong></dt> <dd> <p>Traces the messages the process receives and sends.</p> </dd> <dt><strong><span class="code">c (call)</span></strong></dt> <dd> <p>Traces global function calls for the process according to the trace patterns set in the system (see tp/2).</p> </dd> <dt><strong><span class="code">p (procs)</span></strong></dt> <dd> <p>Traces process related events to the process.</p> </dd> <dt><strong><span class="code">sos (set on spawn)</span></strong></dt> <dd> <p>Lets all processes created by the traced process inherit the trace flags of the traced process.</p> </dd> <dt><strong><span class="code">sol (set on link)</span></strong></dt> <dd> <p>Lets another process, <span class="code">P2</span>, inherit the trace flags of the traced process whenever the traced process links to <span class="code">P2</span>.</p> </dd> <dt><strong><span class="code">sofs (set on first spawn)</span></strong></dt> <dd> <p>This is the same as <span class="code">sos</span>, but only for the first process spawned by the traced process.</p> </dd> <dt><strong><span class="code">sofl (set on first link)</span></strong></dt> <dd> <p>This is the same as <span class="code">sol</span>, but only for the first call to <span class="code">link/1</span> by the traced process.</p> </dd> <dt><strong><span class="code">all</span></strong></dt> <dd> <p>Sets all flags.</p> </dd> <dt><strong><span class="code">clear</span></strong></dt> <dd> <p>Clears all flags. </p> </dd> </dl> <p>The list can also include any of the flags allowed in <span class="code">erlang:trace/3</span></p> <p>The function returns either an error tuple or a tuple <span class="code">{ok, List}</span>. The <span class="code">List</span> consists of specifications of how many processes that matched (in the case of a pure pid() exactly 1). The specification of matched processes is <span class="code">{matched, Node, N}</span>. If the remote processor call,<span class="code">rpc</span>, to a remote node fails, the <span class="code">rpc</span> error message is delivered as a fourth argument and the number of matched processes are 0. Note that the result {ok, List} may contain a list where <span class="code">rpc</span> calls to one, several or even all nodes failed.</p> </p></div> <p><a name="c-3"><span class="bold_code">c(Mod, Fun, Args)</span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">c(Mod, Fun, Args, all)</span>.</p> </p></div> <p><a name="c-4"><span class="bold_code">c(Mod, Fun, Args, Flags)</span></a><br></p> <div class="REFBODY"><p> <p>Evaluates the expression <span class="code">apply(Mod, Fun, Args)</span> with the trace flags in <span class="code">Flags</span> set. This is a convenient way to trace processes from the Erlang shell.</p> </p></div> <p><a name="i-0"><span class="bold_code">i() -> ok</span></a><br></p> <div class="REFBODY"><p> <p>Displays information about all traced processes.</p> </p></div> <p><a name="tp-2"><span class="bold_code">tp(Module,MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tp({Module, '_', '_'}, MatchSpec)</p> </p></div> <p><a name="tp-3"><span class="bold_code">tp(Module,Function,MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tp({Module, Function, '_'}, MatchSpec)</p> </p></div> <p><a name="tp-4"><span class="bold_code">tp(Module, Function, Arity, MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tp({Module, Function, Arity}, MatchSpec)</p> </p></div> <p><a name="tp-2"><span class="bold_code">tp({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Module = atom() | '_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Function = atom() | '_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Arity = integer() |'_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchSpec = integer() | atom() | [] | match_spec()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchDesc = [MatchInfo]</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchInfo = {saved, integer()} | MatchNum</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</span><br> </div> </div> <div class="REFBODY"><p> <p>This function enables call trace for one or more functions. All exported functions matching the <span class="code">{Module, Function, Arity}</span> argument will be concerned, but the <span class="code">match_spec()</span> may further narrow down the set of function calls generating trace messages.</p> <p>For a description of the <span class="code">match_spec()</span> syntax, please turn to the <strong>User's guide</strong> part of the online documentation for the runtime system (<strong>erts</strong>). The chapter <strong>Match Specification in Erlang</strong> explains the general match specification "language".</p> <p>The Module, Function and/or Arity parts of the tuple may be specified as the atom <span class="code">'_'</span> which is a "wild-card" matching all modules/functions/arities. Note, if the Module is specified as <span class="code">'_'</span>, the Function and Arity parts have to be specified as '_' too. The same holds for the Functions relation to the Arity.</p> <p>All nodes added with <span class="code">n/1</span> or <span class="code">tracer/0/2/3</span> will be affected by this call, and if Module is not <span class="code">'_'</span> the module will be loaded on all nodes.</p> <p>The function returns either an error tuple or a tuple <span class="code">{ok, List}</span>. The <span class="code">List</span> consists of specifications of how many functions that matched, in the same way as the processes are presented in the return value of <span class="code">p/2</span>. </p> <p>There may be a tuple <span class="code">{saved, N}</span> in the return value, if the MatchSpec is other than []. The integer <span class="code">N</span> may then be used in subsequent calls to this function and will stand as an "alias" for the given expression. There are also built-in aliases named with atoms (see also <span class="code">ltp/0</span> below).</p> <p>If an error is returned, it can be due to errors in compilation of the match specification. Such errors are presented as a list of tuples <span class="code">{error, string()}</span> where the string is a textual explanation of the compilation error. An example:</p> <div class="example"><pre> (x@y)4> <span class="bold_code">dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).</span> {error, [{error,"Special form 'message' called with wrong number of arguments in {message,two,arguments}."}, {error,"Function noexist/1 does_not_exist."}]}</pre></div> </p></div> <p><a name="tpl-2"><span class="bold_code">tpl(Module,MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tpl({Module, '_', '_'}, MatchSpec)</p> </p></div> <p><a name="tpl-3"><span class="bold_code">tpl(Module,Function,MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tpl({Module, Function, '_'}, MatchSpec)</p> </p></div> <p><a name="tpl-4"><span class="bold_code">tpl(Module, Function, Arity, MatchSpec)</span></a><br></p> <div class="REFBODY"><p> <p>Same as tpl({Module, Function, Arity}, MatchSpec)</p> </p></div> <p><a name="tpl-2"><span class="bold_code">tpl({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"><p> <p>This function works as <span class="code">tp/2</span>, but enables tracing for local calls (and local functions) as well as for global calls (and functions).</p> </p></div> <p><a name="ctp-0"><span class="bold_code">ctp()</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctp({'_', '_', '_'})</p> </p></div> <p><a name="ctp-1"><span class="bold_code">ctp(Module)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctp({Module, '_', '_'})</p> </p></div> <p><a name="ctp-2"><span class="bold_code">ctp(Module, Function)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctp({Module, Function, '_'})</p> </p></div> <p><a name="ctp-3"><span class="bold_code">ctp(Module, Function, Arity)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctp({Module, Function, Arity})</p> </p></div> <p><a name="ctp-1"><span class="bold_code">ctp({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Module = atom() | '_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Function = atom() | '_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Arity = integer() | '_'</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchDesc = [MatchNum]</span><br> </div> <div class="REFTYPES"> <span class="bold_code">MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</span><br> </div> </div> <div class="REFBODY"><p> <p>This function disables call tracing on the specified functions. The semantics of the parameter is the same as for the corresponding function specification in <span class="code">tp/2</span> or <span class="code">tpl/2</span>. Both local and global call trace is disabled. </p> <p>The return value reflects how many functions that matched, and is constructed as described in <span class="code">tp/2</span>. No tuple <span class="code">{saved, N}</span> is however ever returned (for obvious reasons).</p> </p></div> <p><a name="ctpl-0"><span class="bold_code">ctpl()</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpl({'_', '_', '_'})</p> </p></div> <p><a name="ctpl-1"><span class="bold_code">ctpl(Module)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpl({Module, '_', '_'})</p> </p></div> <p><a name="ctpl-2"><span class="bold_code">ctpl(Module, Function)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpl({Module, Function, '_'})</p> </p></div> <p><a name="ctpl-3"><span class="bold_code">ctpl(Module, Function, Arity)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpl({Module, Function, Arity})</p> </p></div> <p><a name="ctpl-1"><span class="bold_code">ctpl({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"><p> <p>This function works as <span class="code">ctp/1</span>, but only disables tracing set up with <span class="code">tpl/2</span> (not with <span class="code">tp/2</span>).</p> </p></div> <p><a name="ctpg-0"><span class="bold_code">ctpg()</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpg({'_', '_', '_'})</p> </p></div> <p><a name="ctpg-1"><span class="bold_code">ctpg(Module)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpg({Module, '_', '_'})</p> </p></div> <p><a name="ctpg-2"><span class="bold_code">ctpg(Module, Function)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpg({Module, Function, '_'})</p> </p></div> <p><a name="ctpg-3"><span class="bold_code">ctpg(Module, Function, Arity)</span></a><br></p> <div class="REFBODY"><p> <p>Same as ctpg({Module, Function, Arity})</p> </p></div> <p><a name="ctpg-1"><span class="bold_code">ctpg({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</span></a><br></p> <div class="REFBODY"><p> <p>This function works as <span class="code">ctp/1</span>, but only disables tracing set up with <span class="code">tp/2</span> (not with <span class="code">tpl/2</span>).</p> </p></div> <p><a name="ltp-0"><span class="bold_code">ltp() -> ok</span></a><br></p> <div class="REFBODY"><p> <p>Use this function to recall all match specifications previously used in the session (i. e. previously saved during calls to <span class="code">tp/2</span>, and built-in match specifications. This is very useful, as a complicated match_spec can be quite awkward to write. Note that the match specifications are lost if <span class="code">stop/0</span> is called.</p> <p>Match specifications used can be saved in a file (if a read-write file system is present) for use in later debugging sessions, see <span class="code">wtp/1</span> and <span class="code">rtp/1</span></p> </p></div> <p><a name="dtp-0"><span class="bold_code">dtp() -> ok</span></a><br></p> <div class="REFBODY"><p> <p>Use this function to "forget" all match specifications saved during calls to <span class="code">tp/2</span>. This is useful when one wants to restore other match specifications from a file with <span class="code">rtp/1</span>. Use <span class="code">dtp/1</span> to delete specific saved match specifications. </p> </p></div> <p><a name="dtp-1"><span class="bold_code">dtp(N) -> ok</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">N = integer()</span><br> </div> </div> <div class="REFBODY"><p> <p>Use this function to "forget" a specific match specification saved during calls to <span class="code">tp/2</span>.</p> </p></div> <p><a name="wtp-1"><span class="bold_code">wtp(Name) -> ok | {error, IOError}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Name = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">IOError = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function will save all match specifications saved during the session (during calls to <span class="code">tp/2</span>) and built-in match specifications in a text file with the name designated by <span class="code">Name</span>. The format of the file is textual, why it can be edited with an ordinary text editor, and then restored with <span class="code">rtp/1</span>. </p> <p>Each match spec in the file ends with a full stop (<span class="code">.</span>) and new (syntactically correct) match specifications can be added to the file manually.</p> <p>The function returns <span class="code">ok</span> or an error tuple where the second element contains the I/O error that made the writing impossible.</p> </p></div> <p><a name="rtp-1"><span class="bold_code">rtp(Name) -> ok | {error, Error}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Name = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Error = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function reads match specifications from a file (possibly) generated by the <span class="code">wtp/1</span> function. It checks the syntax of all match specifications and verifies that they are correct. The error handling principle is "all or nothing", i. e. if some of the match specifications are wrong, none of the specifications are added to the list of saved match specifications for the running system. </p> <p>The match specifications in the file are <strong>merged</strong> with the current match specifications, so that no duplicates are generated. Use <span class="code">ltp/0</span> to see what numbers were assigned to the specifications from the file.</p> <p>The function will return an error, either due to I/O problems (like a non existing or non readable file) or due to file format problems. The errors from a bad format file are in a more or less textual format, which will give a hint to what's causing the problem. <a name="n"></a> </p> </p></div> <p><a name="n-1"><span class="bold_code">n(Nodename) -> {ok, Nodename} | {error, Reason}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Nodename = atom()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Reason = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>The <span class="code">dbg</span> server keeps a list of nodes where tracing should be performed. Whenever a <span class="code">tp/2</span> call or a <span class="code">p/2</span> call is made, it is executed for all nodes in this list including the local node (except for <span class="code">p/2</span> with a specific <span class="code">pid()</span> as first argument, in which case the command is executed only on the node where the designated process resides). </p> <p>This function adds a remote node (<span class="code">Nodename</span>) to the list of nodes where tracing is performed. It starts a tracer process on the remote node, which will send all trace messages to the tracer process on the local node (via the Erlang distribution). If no tracer process is running on the local node, the error reason <span class="code">no_local_tracer</span> is returned. The tracer process on the local node must be started with the <span class="code">tracer/0/2</span> function. </p> <p>If <span class="code">Nodename</span> is the local node, the error reason <span class="code">cant_add_local_node</span> is returned. </p> <p>If a trace port (<span class="bold_code"><a href="#trace_port">see</a></span><span class="code">trace_port/2</span>) is running on the local node, remote nodes can not be traced with a tracer process. The error reason <span class="code">cant_trace_remote_pid_to_local_port</span> is returned. A trace port can however be started on the remote node with the <span class="code">tracer/3</span> function. </p> <p>The function will also return an error if the node <span class="code">Nodename</span> is not reachable.</p> </p></div> <p><a name="cn-1"><span class="bold_code">cn(Nodename) -> ok</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Nodename = atom()</span><br> </div> </div> <div class="REFBODY"><p> <p>Clears a node from the list of traced nodes. Subsequent calls to <span class="code">tp/2</span> and <span class="code">p/2</span> will not consider that node, but tracing already activated on the node will continue to be in effect.</p> <p>Returns <span class="code">ok</span>, cannot fail.</p> </p></div> <p><a name="ln-0"><span class="bold_code">ln() -> ok</span></a><br></p> <div class="REFBODY"><p> <p>Shows the list of traced nodes on the console.</p> </p></div> <p><a name="tracer-0"><span class="bold_code">tracer() -> {ok, pid()} | {error, already_started}</span></a><br></p> <div class="REFBODY"><p> <p>This function starts a server on the local node that will be the recipient of all trace messages. All subsequent calls to <span class="code">p/2</span> will result in messages sent to the newly started trace server.</p> <p>A trace server started in this way will simply display the trace messages in a formatted way in the Erlang shell (i. e. use io:format). See <span class="code">tracer/2</span> for a description of how the trace message handler can be customized. <a name="tracer2"></a> </p> <p>To start a similar tracer on a remote node, use <span class="code">n/1</span>.</p> </p></div> <p><a name="tracer-2"><span class="bold_code">tracer(Type, Data) -> {ok, pid()} | {error, Error}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Type = port | process</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Data = PortGenerator | HandlerSpec</span><br> </div> <div class="REFTYPES"> <span class="bold_code">HandlerSpec = {HandlerFun, InitialData}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">HandlerFun = fun() (two arguments)</span><br> </div> <div class="REFTYPES"> <span class="bold_code">InitialData = term()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">PortGenerator = fun() (no arguments)</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Error = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function starts a tracer server with additional parameters on the local node. The first parameter, the <span class="code">Type</span>, indicates if trace messages should be handled by a receiving process (<span class="code">process</span>) or by a tracer port (<span class="code">port</span>). For a description about tracer ports see <span class="code">trace_port/2</span>. </p> <p>If <span class="code">Type</span> is a process, a message handler function can be specified (<span class="code">HandlerSpec</span>). The handler function, which should be a <span class="code">fun</span> taking two arguments, will be called for each trace message, with the first argument containing the message as it is and the second argument containing the return value from the last invocation of the fun. The initial value of the second parameter is specified in the <span class="code">InitialData</span> part of the <span class="code">HandlerSpec</span>. The <span class="code">HandlerFun</span> may chose any appropriate action to take when invoked, and can save a state for the next invocation by returning it. </p> <p>If <span class="code">Type</span> is a port, then the second parameter should be a <strong>fun</strong> which takes no arguments and returns a newly opened trace port when called. Such a <strong>fun</strong> is preferably generated by calling <span class="code">trace_port/2</span>. </p> <p>If an error is returned, it can either be due to a tracer server already running (<span class="code">{error,already_started}</span>) or due to the <span class="code">HandlerFun</span> throwing an exception. </p> <p>To start a similar tracer on a remote node, use <span class="code">tracer/3</span>. <a name="trace_port"></a> </p> </p></div> <p><a name="tracer-3"><span class="bold_code">tracer(Nodename, Type, Data) -> {ok, Nodename} | {error, Reason}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Nodename = atom()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function is equivalent to <span class="code">tracer/2</span>, but acts on the given node. A tracer is started on the node (<span class="code">Nodename</span>) and the node is added to the list of traced nodes. </p> <div class="note"> <div class="label">Note</div> <div class="content"><p> <p>This function is not equivalent to <span class="code">n/1</span>. While <span class="code">n/1</span> starts a process tracer which redirects all trace information to a process tracer on the local node (i.e. the trace control node), <span class="code">tracer/3</span> starts a tracer of any type which is independent of the tracer on the trace control node.</p> </p></div> </div> <p>For details, <span class="bold_code"><a href="#tracer2">see</a></span><span class="code">tracer/2</span>.</p> </p></div> <p><a name="trace_port-2"><span class="bold_code">trace_port(Type, Parameters) -> fun()</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Type = ip | file</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Parameters = Filename | WrapFilesSpec | IPPortSpec</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Filename = string() | [string()] | atom()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapFilesSpec = {Filename, wrap, Suffix} | {Filename, wrap, Suffix, WrapSize} | {Filename, wrap, Suffix, WrapSize, WrapCnt}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Suffix = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapSize = integer() >= 0 | {time, WrapTime}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapTime = integer() >= 1</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapCnt = integer() >= 1</span><br> </div> <div class="REFTYPES"> <span class="bold_code">IpPortSpec = PortNumber | {PortNumber, QueSize}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">PortNumber = integer()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">QueSize = integer()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function creates a trace port generating <strong>fun</strong>. The <strong>fun</strong> takes no arguments and returns a newly opened trace port. The return value from this function is suitable as a second parameter to tracer/2, i. e. <span class="code">dbg:tracer(port, dbg:trace_port(ip, 4711))</span>. </p> <p>A trace port is an Erlang port to a dynamically linked in driver that handles trace messages directly, without the overhead of sending them as messages in the Erlang virtual machine.</p> <p>Two trace drivers are currently implemented, the <span class="code">file</span> and the <span class="code">ip</span> trace drivers. The file driver sends all trace messages into one or several binary files, from where they later can be fetched and processed with the <span class="code">trace_client/2</span> function. The ip driver opens a TCP/IP port where it listens for connections. When a client (preferably started by calling <span class="code">trace_client/2</span> on another Erlang node) connects, all trace messages are sent over the IP network for further processing by the remote client. </p> <p>Using a trace port significantly lowers the overhead imposed by using tracing.</p> <p>The file trace driver expects a filename or a wrap files specification as parameter. A file is written with a high degree of buffering, why all trace messages are <strong>not</strong> guaranteed to be saved in the file in case of a system crash. That is the price to pay for low tracing overhead.</p> <p>A wrap files specification is used to limit the disk space consumed by the trace. The trace is written to a limited number of files each with a limited size. The actual filenames are <span class="code">Filename ++ SeqCnt ++ Suffix</span>, where <span class="code">SeqCnt</span> counts as a decimal string from <span class="code">0</span> to <span class="code">WrapCnt</span> and then around again from <span class="code">0</span>. When a trace term written to the current file makes it longer than <span class="code">WrapSize</span>, that file is closed, if the number of files in this wrap trace is as many as <span class="code">WrapCnt</span> the oldest file is deleted then a new file is opened to become the current. Thus, when a wrap trace has been stopped, there are at most <span class="code">WrapCnt</span> trace files saved with a size of at least <span class="code">WrapSize</span> (but not much bigger), except for the last file that might even be empty. The default values are <span class="code">WrapSize = 128*1024</span> and <span class="code">WrapCnt = 8</span>.</p> <p>The <span class="code">SeqCnt</span> values in the filenames are all in the range <span class="code">0</span> through <span class="code">WrapCnt</span> with a gap in the circular sequence. The gap is needed to find the end of the trace.</p> <p>If the <span class="code">WrapSize</span> is specified as <span class="code">{time, WrapTime}</span>, the current file is closed when it has been open more than <span class="code">WrapTime</span> milliseconds, regardless of it being empty or not.</p> <p>The ip trace driver has a queue of <span class="code">QueSize</span> messages waiting to be delivered. If the driver cannot deliver messages as fast as they are produced by the runtime system, a special message is sent, which indicates how many messages that are dropped. That message will arrive at the handler function specified in <span class="code">trace_client/3</span> as the tuple <span class="code">{drop, N}</span> where <span class="code">N</span> is the number of consecutive messages dropped. In case of heavy tracing, drop's are likely to occur, and they surely occur if no client is reading the trace messages.</p> </p></div> <p><a name="flush_trace_port-0"><span class="bold_code">flush_trace_port()</span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">flush_trace_port(node())</span>.</p> </p></div> <p><a name="flush_trace_port-1"><span class="bold_code">flush_trace_port(Nodename) -> ok | {error, Reason}</span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">trace_port_control(Nodename,flush)</span>.</p> </p></div> <p><a name="trace_port_control-1"><span class="bold_code">trace_port_control(Operation)</span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">trace_port_control(node(),Operation)</span>.</p> </p></div> <p><a name="trace_port_control-2"><span class="bold_code">trace_port_control(Nodename,Operation) -> ok | {ok, Result} | {error, Reason}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Nodename = atom()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function is used to do a control operation on the active trace port driver on the given node (<span class="code">Nodename</span>). Which operations that are allowed as well as their return values are depending on which trace driver that is used.</p> <p>Returns either <span class="code">ok</span> or <span class="code">{ok, Result}</span> if the operation was successful, or <span class="code">{error, Reason}</span> if the current tracer is a process or if it is a port not supporting the operation.</p> <p>The allowed values for <span class="code">Operation</span> are:</p> <dl> <dt><strong><span class="code">flush</span></strong></dt> <dd> <p>This function is used to flush the internal buffers held by a trace port driver. Currently only the file trace driver supports this operation. Returns <span class="code">ok</span>.</p> </dd> <dt><strong><span class="code">get_listen_port</span></strong></dt> <dd> <p>Returns <span class="code">{ok, IpPort}</span> where <span class="code">IpPort</span>is the IP port number used by the driver listen socket. Only the ip trace driver supports this operation.</p> </dd> </dl> </p></div> <p><a name="trace_client-2"><span class="bold_code">trace_client(Type, Parameters) -> pid()</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Type = ip | file | follow_file</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Parameters = Filename | WrapFilesSpec | IPClientPortSpec</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Filename = string() | [string()] | atom()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapFilesSpec = see trace_port/2</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Suffix = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">IpClientPortSpec = PortNumber | {Hostname, PortNumber}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">PortNumber = integer()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Hostname = string()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function starts a trace client that reads the output created by a trace port driver and handles it in mostly the same way as a tracer process created by the <span class="code">tracer/0</span> function.</p> <p>If <span class="code">Type</span> is <span class="code">file</span>, the client reads all trace messages stored in the file named <span class="code">Filename</span> or specified by <span class="code">WrapFilesSpec</span> (must be the same as used when creating the trace, see trace_port/2) and let's the default handler function format the messages on the console. This is one way to interpret the data stored in a file by the file trace port driver.</p> <p>If <span class="code">Type</span> is <span class="code">follow_file</span>, the client behaves as in the <span class="code">file</span> case, but keeps trying to read (and process) more data from the file until stopped by <span class="code">stop_trace_client/1</span>. <span class="code">WrapFilesSpec</span> is not allowed as second argument for this <span class="code">Type</span>.</p> <p>If <span class="code">Type</span> is <span class="code">ip</span>, the client connects to the TCP/IP port <span class="code">PortNumber</span> on the host <span class="code">Hostname</span>, from where it reads trace messages until the TCP/IP connection is closed. If no <span class="code">Hostname</span> is specified, the local host is assumed.</p> <p>As an example, one can let trace messages be sent over the network to another Erlang node (preferably <strong>not</strong> distributed), where the formatting occurs:</p> <p>On the node <span class="code">stack</span> there's an Erlang node <span class="code">ant@stack</span>, in the shell, type the following:</p> <div class="example"><pre> ant@stack> <span class="bold_code">dbg:tracer(port, dbg:trace_port(ip,4711)).</span> <0.17.0> ant@stack> <span class="bold_code">dbg:p(self(), send).</span> {ok,1}</pre></div> <p>All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on another node, preferably on another host, we do like this:</p> <div class="example"><pre> -> <span class="bold_code">dbg:trace_client(ip, {"stack", 4711}).</span> <0.42.0></pre></div> <p>If we now send a message from the shell on the node <span class="code">ant@stack</span>, where all sends from the shell are traced:</p> <div class="example"><pre> ant@stack> <span class="bold_code">self() ! hello.</span> hello</pre></div> <p>The following will appear at the console on the node that started the trace client:</p> <div class="example"><pre> (<0.23.0>) <0.23.0> ! hello (<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}</pre></div> <p>The last line is generated due to internal message passing in the Erlang shell. The process id's will vary.</p> </p></div> <p><a name="trace_client-3"><span class="bold_code">trace_client(Type, Parameters, HandlerSpec) -> pid()</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Type = ip | file | follow_file</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Parameters = Filename | WrapFilesSpec | IPClientPortSpec</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Filename = string() | [string()] | atom()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">WrapFilesSpec = see trace_port/2</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Suffix = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">IpClientPortSpec = PortNumber | {Hostname, PortNumber}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">PortNumber = integer()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Hostname = string()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">HandlerSpec = {HandlerFun, InitialData}</span><br> </div> <div class="REFTYPES"> <span class="bold_code">HandlerFun = fun() (two arguments)</span><br> </div> <div class="REFTYPES"> <span class="bold_code">InitialData = term()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function works exactly as <span class="code">trace_client/2</span>, but allows you to write your own handler function. The handler function works mostly as the one described in <span class="code">tracer/2</span>, but will also have to be prepared to handle trace messages of the form <span class="code">{drop, N}</span>, where <span class="code">N</span> is the number of dropped messages. This pseudo trace message will only occur if the ip trace driver is used.</p> <p>For trace type <span class="code">file</span>, the pseudo trace message <span class="code">end_of_trace</span> will appear at the end of the trace. The return value from the handler function is in this case ignored.</p> </p></div> <p><a name="stop_trace_client-1"><span class="bold_code">stop_trace_client(Pid) -> ok</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Pid = pid()</span><br> </div> </div> <div class="REFBODY"><p> <p>This function shuts down a previously started trace client. The <span class="code">Pid</span> argument is the process id returned from the <span class="code">trace_client/2</span> or <span class="code">trace_client/3</span> call.</p> </p></div> <p><a name="get_tracer-0"><span class="bold_code">get_tracer()</span></a><br></p> <div class="REFBODY"><p> <p>Equivalent to <span class="code">get_tracer(node())</span>.</p> </p></div> <p><a name="get_tracer-1"><span class="bold_code">get_tracer(Nodename) -> {ok, Tracer}</span></a><br></p> <div class="REFBODY"> <p>Types:</p> <div class="REFTYPES"> <span class="bold_code">Nodename = atom()</span><br> </div> <div class="REFTYPES"> <span class="bold_code">Tracer = port() | pid()</span><br> </div> </div> <div class="REFBODY"><p> <p>Returns the process or port to which all trace messages are sent. </p> </p></div> <p><a name="stop-0"><span class="bold_code">stop() -> stopped</span></a><br></p> <div class="REFBODY"><p> <p>Stops the <span class="code">dbg</span> server and clears all trace flags for all processes and all trace patterns for all functions. Also shuts down all trace clients and closes all trace ports.</p> <p>Note that no trace patterns are affected by this function.</p> </p></div> <p><a name="stop_clear-0"><span class="bold_code">stop_clear() -> stopped</span></a><br></p> <div class="REFBODY"><p> <p>Same as stop/0, but also clears all trace patterns on local and global functions calls.</p> </p></div> <h3><a name="id2261069">Simple examples - tracing from the shell</a></h3> <div class="REFBODY"> <a name="simple_example"></a> <p>The simplest way of tracing from the Erlang shell is to use <span class="code">dbg:c/3</span> or <span class="code">dbg:c/4</span>, e.g. tracing the function <span class="code">dbg:get_tracer/0</span>:</p> <div class="example"><pre> (tiger@durin)84> <span class="bold_code">dbg:c(dbg,get_tracer,[]).</span> (<0.154.0>) <0.152.0> ! {<0.154.0>,{get_tracer,tiger@durin}} (<0.154.0>) out {dbg,req,1} (<0.154.0>) << {dbg,{ok,<0.153.0>}} (<0.154.0>) in {dbg,req,1} (<0.154.0>) << timeout {ok,<0.153.0>} (tiger@durin)85></pre></div> <p>Another way of tracing from the shell is to explicitly start a <strong>tracer</strong> and then set the <strong>trace flags</strong> of your choice on the processes you want to trace, e.g. trace messages and process events:</p> <div class="example"><pre> (tiger@durin)66> <span class="bold_code">Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).</span> <0.126.0> (tiger@durin)67> <span class="bold_code">dbg:tracer().</span> {ok,<0.128.0>} (tiger@durin)68> <span class="bold_code">dbg:p(Pid,[m,procs]).</span> {ok,[{matched,tiger@durin,1}]} (tiger@durin)69> <span class="bold_code">Pid ! {self(),hello}.</span> (<0.126.0>) << {<0.116.0>,hello} {<0.116.0>,hello} (<0.126.0>) << timeout (<0.126.0>) <0.116.0> ! hello (<0.126.0>) exit normal (tiger@durin)70> <span class="bold_code">flush().</span> Shell got hello ok (tiger@durin)71></pre></div> <p>If you set the <span class="code">call</span> trace flag, you also have to set a <strong>trace pattern</strong> for the functions you want to trace:</p> <div class="example"><pre> (tiger@durin)77> <span class="bold_code">dbg:tracer().</span> {ok,<0.142.0>} (tiger@durin)78> <span class="bold_code">dbg:p(all,call).</span> {ok,[{matched,tiger@durin,3}]} (tiger@durin)79> <span class="bold_code">dbg:tp(dbg,get_tracer,0,[]).</span> {ok,[{matched,tiger@durin,1}]} (tiger@durin)80> <span class="bold_code">dbg:get_tracer().</span> (<0.116.0>) call dbg:get_tracer() {ok,<0.143.0>} (tiger@durin)81> <span class="bold_code">dbg:tp(dbg,get_tracer,0,[{'_',[],[{return_trace}]}]).</span> {ok,[{matched,tiger@durin,1},{saved,1}]} (tiger@durin)82> <span class="bold_code">dbg:get_tracer().</span> (<0.116.0>) call dbg:get_tracer() (<0.116.0>) returned from dbg:get_tracer/0 -> {ok,<0.143.0>} {ok,<0.143.0>} (tiger@durin)83></pre></div> </div> <h3><a name="id2261197">Advanced topics - combining with seq_trace</a></h3> <div class="REFBODY"> <a name="advanced"></a> <p>The <span class="code">dbg</span> module is primarily targeted towards tracing through the <span class="code">erlang:trace/3</span> function. It is sometimes desired to trace messages in a more delicate way, which can be done with the help of the <span class="code">seq_trace</span> module. </p> <p><span class="code">seq_trace</span> implements sequential tracing (known in the AXE10 world, and sometimes called "forlopp tracing"). <span class="code">dbg</span> can interpret messages generated from <span class="code">seq_trace</span> and the same tracer function for both types of tracing can be used. The <span class="code">seq_trace</span> messages can even be sent to a trace port for further analysis. </p> <p>As a match specification can turn on sequential tracing, the combination of <span class="code">dbg</span> and <span class="code">seq_trace</span> can be quite powerful. This brief example shows a session where sequential tracing is used:</p> <div class="example"><pre> 1> <span class="bold_code">dbg:tracer().</span> {ok,<0.30.0>} 2> <span class="bold_code">{ok, Tracer} = dbg:get_tracer().</span> {ok,<0.31.0>} 3> <span class="bold_code">seq_trace:set_system_tracer(Tracer).</span> false 4> <span class="bold_code">dbg:tp(dbg, get_tracer, 0, [{[],[],[{set_seq_token, send, true}]}]).</span> {ok,[{matched,nonode@nohost,1},{saved,1}]} 5> <span class="bold_code">dbg:p(all,call).</span> {ok,[{matched,nonode@nohost,22}]} 6> <span class="bold_code">dbg:get_tracer(), seq_trace:set_token([]).</span> (<0.25.0>) call dbg:get_tracer() SeqTrace [0]: (<0.25.0>) <0.30.0> ! {<0.25.0>,get_tracer} [Serial: {2,4}] SeqTrace [0]: (<0.30.0>) <0.25.0> ! {dbg,{ok,<0.31.0>}} [Serial: {4,5}] {1,0,5,<0.30.0>,4}</pre></div> <p>This session sets the system_tracer to the same process as the ordinary tracer process (i. e. <0.31.0>) and sets the trace pattern for the function <span class="code">dbg:get_tracer</span> to one that has the action of setting a sequential token. When the function is called by a traced process (all processes are traced in this case), the process gets "contaminated" by the token and <span class="code">seq_trace</span> messages are sent both for the server request and the response. The <span class="code">seq_trace:set_token([])</span> after the call clears the <span class="code">seq_trace</span> token, why no messages are sent when the answer propagates via the shell to the console port. The output would otherwise have been more noisy.</p> </div> <h3><a name="id2261322">Note of caution</a></h3> <div class="REFBODY"> <p>When tracing function calls on a group leader process (an IO process), there is risk of causing a deadlock. This will happen if a group leader process generates a trace message and the tracer process, by calling the trace handler function, sends an IO request to the same group leader. The problem can only occur if the trace handler prints to tty using an <span class="code">io</span> function such as <span class="code">format/2</span>. Note that when <span class="code">dbg:p(all,call)</span> is called, IO processes are also traced. Here's an example:</p> <div class="example"><pre> %% Using a default line editing shell 1> <span class="bold_code">dbg:tracer(process, {fun(Msg,_) -> io:format("~p~n", [Msg]), 0 end, 0}).</span> {ok,<0.37.0>} 2> <span class="bold_code">dbg:p(all, [call]).</span> {ok,[{matched,nonode@nohost,25}]} 3> <span class="bold_code">dbg:tp(mymod,[{'_',[],[]}]).</span> {ok,[{matched,nonode@nohost,0},{saved,1}]} 4> <span class="bold_code">mymod:</span> % TAB pressed here %% -- Deadlock --</pre></div> <p>Here's another example:</p> <div class="example"><pre> %% Using a shell without line editing (oldshell) 1> <span class="bold_code">dbg:tracer(process).</span> {ok,<0.31.0>} 2> <span class="bold_code">dbg:p(all, [call]).</span> {ok,[{matched,nonode@nohost,25}]} 3> <span class="bold_code">dbg:tp(lists,[{'_',[],[]}]).</span> {ok,[{matched,nonode@nohost,0},{saved,1}]} % -- Deadlock --</pre></div> <p>The reason we get a deadlock in the first example is because when TAB is pressed to expand the function name, the group leader (which handles character input) calls <span class="code">mymod:module_info()</span>. This generates a trace message which, in turn, causes the tracer process to send an IO request to the group leader (by calling <span class="code">io:format/2</span>). We end up in a deadlock.</p> <p>In the second example we use the default trace handler function. This handler prints to tty by sending IO requests to the <span class="code">user</span> process. When Erlang is started in oldshell mode, the shell process will have <span class="code">user</span> as its group leader and so will the tracer process in this example. Since <span class="code">user</span> calls functions in <span class="code">lists</span> we end up in a deadlock as soon as the first IO request is sent.</p> <p>Here are a few suggestions for how to avoid deadlock:</p> <ul> <li>Don't trace the group leader of the tracer process. If tracing has been switched on for all processes, call <span class="code">dbg:p(TracerGLPid,clear)</span> to stop tracing the group leader (<span class="code">TracerGLPid</span>). <span class="code">process_info(TracerPid,group_leader)</span> tells you which process this is (<span class="code">TracerPid</span> is returned from <span class="code">dbg:get_tracer/0</span>).</li> <li>Don't trace the <span class="code">user</span> process if using the default trace handler function.</li> <li>In your own trace handler function, call <span class="code">erlang:display/1</span> instead of an <span class="code">io</span> function or, if <span class="code">user</span> is not used as group leader, print to <span class="code">user</span> instead of the default group leader. Example: <span class="code">io:format(user,Str,Args)</span>.</li> </ul> </div> </div> <div class="footer"> <hr> <p>Copyright © 1999-2010 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>