aboutsummaryrefslogtreecommitdiffstats
path: root/lib/runtime_tools/doc/src/dbg.xml
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/runtime_tools/doc/src/dbg.xml
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/runtime_tools/doc/src/dbg.xml')
-rw-r--r--lib/runtime_tools/doc/src/dbg.xml1187
1 files changed, 1187 insertions, 0 deletions
diff --git a/lib/runtime_tools/doc/src/dbg.xml b/lib/runtime_tools/doc/src/dbg.xml
new file mode 100644
index 0000000000..0e63649c09
--- /dev/null
+++ b/lib/runtime_tools/doc/src/dbg.xml
@@ -0,0 +1,1187 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>1996</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>dbg</title>
+ <prepared>Patrik Nyblom (Claes Wikstrom)</prepared>
+ <responsible></responsible>
+ <docno>1</docno>
+ <approved>ETX/B/SFP (Kenneth Lundin)</approved>
+ <checked></checked>
+ <date>96-11-07</date>
+ <rev>A</rev>
+ <file>dbg.sgml</file>
+ </header>
+ <module>dbg</module>
+ <modulesummary>The Text Based Trace Facility</modulesummary>
+ <description>
+ <p>This module implements a text based interface to the
+ <c>trace/3</c> and the <c>trace_pattern/2</c> 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
+ <c>pman</c> module.
+ </p>
+ <p>For some examples of how to use <c>dbg</c> from the Erlang
+ shell, see the <seealso marker="#simple_example">simple example</seealso> 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 <seealso marker="#advanced">advanced topics</seealso> section.
+ </p>
+ </description>
+ <funcs>
+ <func>
+ <name>fun2ms(LiteralFun) -> MatchSpec</name>
+ <fsummary>Pseudo function that transforms fun syntax to match_spec.</fsummary>
+ <type>
+ <v>LiteralFun = fun() literal</v>
+ <v>MatchSpec = term()</v>
+ </type>
+ <desc>
+ <p>Pseudo function that by means of a <c>parse_transform</c>
+ translates the <em>literal</em><c>fun()</c> typed as parameter in
+ the function call to a match specification as described in
+ the <c>match_spec</c> manual of <c>ERTS</c> users guide.
+ (with literal I mean that the <c>fun()</c> 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
+ <c>ms_transform</c> and the source <em>must</em> include the
+ file <c>ms_transform.hrl</c> 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
+ <c>-include_lib("stdlib/include/ms_transform.hrl").</c> to
+ the source file.</p>
+ <p>The <c>fun()</c> 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 <c>is_</c>XXX guard tests and one
+ cannot use language constructs that have no representation
+ in a match_spec (like <c>if</c>, <c>case</c>,
+ <c>receive</c> etc). The return value from the fun will be
+ the return value of the resulting match_spec.</p>
+ <p>Example:</p>
+ <pre>
+1> <input>dbg:fun2ms(fun([M,N]) when N > 3 -> return_trace() end).</input>
+[{['$1','$2'],[{'>','$2',3}],[{return_trace}]}]</pre>
+ <p>Variables from the environment can be imported, so that this
+ works:</p>
+ <pre>
+2> <input>X=3.</input>
+3
+3> <input>dbg:fun2ms(fun([M,N]) when N > X -> return_trace() end).</input>
+[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]</pre>
+ <p>The imported variables will be replaced by match_spec
+ <c>const</c> expressions, which is consistent with the
+ static scoping for Erlang <c>fun()</c>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>
+ <pre>
+4> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atomm(M) -> return_trace() end).</input>
+Error: fun containing local erlang function calls ('is_atomm' called in guard) cannot be translated into match_spec
+{error,transform_error}
+5> <input>dbg:fun2ms(fun([M,N]) when N > X, is_atom(M) -> return_trace() end).</input>
+[{['$1','$2'],[{'>','$2',{const,3}},{is_atom,'$1'}],[{return_trace}]}]</pre>
+ <p>As you can see by the example, the function can be called from
+ the shell too. The <c>fun()</c> 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>
+ <warning>
+ <p>If the parse_transform is not applied to a module which calls this
+ pseudo function, the call will fail in runtime (with a
+ <c>badarg</c>). The module <c>dbg</c> 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
+ <c>parse_transform</c> is properly applied by including
+ the <c>ms_transform.hrl</c> header file, compiled code
+ will never call the function, but the function call is
+ replaced by a literal match_spec.</p>
+ </warning>
+ <p>More information is provided by the <c>ms_transform</c>
+ manual page in STDLIB.</p>
+ </desc>
+ </func>
+ <func>
+ <name>h() -> ok </name>
+ <fsummary>Give a list of available help items on standard output.</fsummary>
+ <desc>
+ <p>Gives a list of items for brief online help.</p>
+ </desc>
+ </func>
+ <func>
+ <name>h(Item) -> ok </name>
+ <fsummary>Give brief help for an item.</fsummary>
+ <type>
+ <v>Item = atom()</v>
+ </type>
+ <desc>
+ <p>Gives a brief help text for functions in the dbg module. The
+ available items can be listed with <c>dbg:h/0</c></p>
+ </desc>
+ </func>
+ <func>
+ <name>p(Item) -> {ok, MatchDesc} | {error, term()} </name>
+ <fsummary>Trace messages to and from Item.</fsummary>
+ <desc>
+ <p>Equivalent to <c>p(Item, [m])</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>p(Item, Flags) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Trace Item according to Flags.</fsummary>
+ <type>
+ <v>MatchDesc = [MatchNum]</v>
+ <v>MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</v>
+ <v>RPCError = term()</v>
+ </type>
+ <desc>
+ <p>Traces <c>Item</c> in accordance to the value specified
+ by <c>Flags</c>. The variation of <c>Item</c> is listed below:</p>
+ <list type="bulleted">
+ <item>If the <c>Item</c> is a <c>pid()</c>, 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 (<seealso marker="#n">see</seealso><c>n/1</c> and <c>tracer/0/2/3</c>).</item>
+ <item>If the <c>Item</c> is the atom <c>all</c>, all processes in the
+ system as well as all processes created hereafter are
+ to be traced. This also affects all nodes added with the
+ <c>n/1</c> or <c>tracer/0/2/3</c> function.</item>
+ <item>If the <c>Item</c> is the atom <c>new</c>, no currently existing
+ processes are affected, but every process created after the
+ call is.This also affects all nodes added with the
+ <c>n/1</c> or <c>tracer/0/2/3</c> function.</item>
+ <item>If the <c>Item</c> is the atom <c>existing</c>, all
+ existing processes are traced, but new processes will not
+ be affected.This also affects all nodes added with the
+ <c>n/1</c> or <c>tracer/0/2/3</c> function.</item>
+ <item>If the <c>Item</c> is an atom other than <c>all</c>,
+ <c>new</c> or <c>existing</c>, 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 <c>n/1</c> or <c>tracer/0/2/3</c> function.</item>
+ <item>If the <c>Item</c> is an integer, the process <c><![CDATA[<0.Item.0>]]></c> is
+ traced.</item>
+ <item>If the <c>Item</c> is a tuple <c>{X, Y, Z}</c>, the
+ process <c><![CDATA[<X.Y.Z>]]></c> is
+ traced. </item>
+ <item>If the <c>Item</c> is a string <![CDATA["<X.Y.Z>"]]>
+ as returned from <c>pid_to_list/1</c>, the process
+ <c><![CDATA[<X.Y.Z>]]></c> is traced. </item>
+ </list>
+ <p><c>Flags</c> can be a single atom,
+ or a list of flags. The available flags are:
+ </p>
+ <taglist>
+ <tag><c>s (send)</c></tag>
+ <item>
+ <p>Traces the messages the process sends.</p>
+ </item>
+ <tag><c>r (receive)</c></tag>
+ <item>
+ <p>Traces the messages the process receives.</p>
+ </item>
+ <tag><c>m (messages)</c></tag>
+ <item>
+ <p>Traces the messages the process receives and sends.</p>
+ </item>
+ <tag><c>c (call)</c></tag>
+ <item>
+ <p>Traces global function calls for the process
+ according to the trace patterns set in the system (see tp/2).</p>
+ </item>
+ <tag><c>p (procs)</c></tag>
+ <item>
+ <p>Traces process related events to the process.</p>
+ </item>
+ <tag><c>sos (set on spawn)</c></tag>
+ <item>
+ <p>Lets all processes created by the traced
+ process inherit the trace flags
+ of the traced process.</p>
+ </item>
+ <tag><c>sol (set on link)</c></tag>
+ <item>
+ <p>Lets another process, <c>P2</c>, inherit the
+ trace flags of the traced
+ process whenever the traced process links to <c>P2</c>.</p>
+ </item>
+ <tag><c>sofs (set on first spawn)</c></tag>
+ <item>
+ <p>This is the same as <c>sos</c>, but only
+ for the first process spawned by the traced process.</p>
+ </item>
+ <tag><c>sofl (set on first link)</c></tag>
+ <item>
+ <p>This is the same as <c>sol</c>, but only for
+ the first call to
+ <c>link/1</c> by the traced process.</p>
+ </item>
+ <tag><c>all</c></tag>
+ <item>
+ <p>Sets all flags.</p>
+ </item>
+ <tag><c>clear</c></tag>
+ <item>
+ <p>Clears all flags.
+ </p>
+ </item>
+ </taglist>
+ <p>The list can also include any of the flags allowed in
+ <c>erlang:trace/3</c></p>
+ <p>The function returns either an error tuple or a tuple
+ <c>{ok, List}</c>. The <c>List</c> consists of
+ specifications of how many processes that matched (in the
+ case of a pure pid() exactly 1). The specification of
+ matched processes is <c>{matched, Node, N}</c>. If the
+ remote processor call,<c>rpc</c>, to a remote node fails,
+ the <c>rpc</c> 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
+ <c>rpc</c> calls to one, several or even all nodes failed.</p>
+ </desc>
+ </func>
+ <func>
+ <name>c(Mod, Fun, Args)</name>
+ <fsummary>Evaluate <c>apply(M,F,Args)</c>with <c>all</c>trace flags set.</fsummary>
+ <desc>
+ <p>Equivalent to <c>c(Mod, Fun, Args, all)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>c(Mod, Fun, Args, Flags)</name>
+ <fsummary>Evaluate <c>apply(M,F,Args)</c>with <c>Flags</c>trace flags set.</fsummary>
+ <desc>
+ <p>Evaluates the expression <c>apply(Mod, Fun, Args)</c> with the trace
+ flags in <c>Flags</c> set. This is a convenient way to trace processes
+ from the Erlang shell.</p>
+ </desc>
+ </func>
+ <func>
+ <name>i() -> ok</name>
+ <fsummary>Display information about all traced processes.</fsummary>
+ <desc>
+ <p>Displays information about all traced processes.</p>
+ </desc>
+ </func>
+ <func>
+ <name>tp(Module,MatchSpec)</name>
+ <fsummary>Set pattern for traced global function calls</fsummary>
+ <desc>
+ <p>Same as tp({Module, '_', '_'}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tp(Module,Function,MatchSpec)</name>
+ <fsummary>Set pattern for traced global function calls</fsummary>
+ <desc>
+ <p>Same as tp({Module, Function, '_'}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tp(Module, Function, Arity, MatchSpec)</name>
+ <fsummary>Set pattern for traced global function calls</fsummary>
+ <desc>
+ <p>Same as tp({Module, Function, Arity}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tp({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Set pattern for traced global function calls</fsummary>
+ <type>
+ <v>Module = atom() | '_'</v>
+ <v>Function = atom() | '_'</v>
+ <v>Arity = integer() |'_'</v>
+ <v>MatchSpec = integer() | atom() | [] | match_spec()</v>
+ <v>MatchDesc = [MatchInfo]</v>
+ <v>MatchInfo = {saved, integer()} | MatchNum</v>
+ <v>MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</v>
+ </type>
+ <desc>
+ <p>This function enables call trace for one or more
+ functions. All exported functions matching the <c>{Module, Function, Arity}</c> argument will be concerned, but the
+ <c>match_spec()</c> may further narrow down the set of function
+ calls generating trace messages.</p>
+ <p>For a description of the <c>match_spec()</c> syntax,
+ please turn to the
+ <em>User's guide</em> part of the online
+ documentation for the runtime system (<em>erts</em>). The
+ chapter <em>Match Specification in Erlang</em> explains the
+ general match specification "language".</p>
+ <p>The Module, Function and/or Arity parts of the tuple may
+ be specified as the atom <c>'_'</c> which is a "wild-card"
+ matching all modules/functions/arities. Note, if the
+ Module is specified as <c>'_'</c>, 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 <c>n/1</c> or <c>tracer/0/2/3</c> will
+ be affected by this call, and if Module is not <c>'_'</c>
+ the module will be loaded on all nodes.</p>
+ <p>The function returns either an error tuple or a tuple
+ <c>{ok, List}</c>. The <c>List</c> consists of specifications of how
+ many functions that matched, in the same way as the processes
+ are presented in the return value of <c>p/2</c>. </p>
+ <p>There may be a tuple <c>{saved, N}</c> in the return value,
+ if the MatchSpec is other
+ than []. The integer <c>N</c> 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 <c>ltp/0</c> 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 <c>{error, string()}</c> where
+ the string is a textual explanation of the compilation
+ error. An example:</p>
+ <pre>
+(x@y)4> <input>dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).</input>
+{error,
+ [{error,"Special form 'message' called with wrong number of
+ arguments in {message,two,arguments}."},
+ {error,"Function noexist/1 does_not_exist."}]}</pre>
+ </desc>
+ </func>
+ <func>
+ <name>tpl(Module,MatchSpec)</name>
+ <fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
+ <desc>
+ <p>Same as tpl({Module, '_', '_'}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tpl(Module,Function,MatchSpec)</name>
+ <fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
+ <desc>
+ <p>Same as tpl({Module, Function, '_'}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tpl(Module, Function, Arity, MatchSpec)</name>
+ <fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
+ <desc>
+ <p>Same as tpl({Module, Function, Arity}, MatchSpec)</p>
+ </desc>
+ </func>
+ <func>
+ <name>tpl({Module, Function, Arity}, MatchSpec) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Set pattern for traced local (as well as global) function calls</fsummary>
+ <desc>
+ <p>This function works as <c>tp/2</c>, but enables
+ tracing for local calls (and local functions) as well as for
+ global calls (and functions).</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctp()</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctp({'_', '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctp(Module)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctp({Module, '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctp(Module, Function)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctp({Module, Function, '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctp(Module, Function, Arity)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctp({Module, Function, Arity})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctp({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <type>
+ <v>Module = atom() | '_'</v>
+ <v>Function = atom() | '_'</v>
+ <v>Arity = integer() | '_'</v>
+ <v>MatchDesc = [MatchNum]</v>
+ <v>MatchNum = {matched, node(), integer()} | {matched, node(), 0, RPCError}</v>
+ </type>
+ <desc>
+ <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
+ <c>tp/2</c> or <c>tpl/2</c>. 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 <c>tp/2</c>. No tuple
+ <c>{saved, N}</c> is however ever returned (for obvious reasons).</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpl()</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpl({'_', '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpl(Module)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpl({Module, '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpl(Module, Function)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpl({Module, Function, '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpl(Module, Function, Arity)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpl({Module, Function, Arity})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpl({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>This function works as <c>ctp/1</c>, but only disables
+ tracing set up with <c>tpl/2</c> (not with <c>tp/2</c>).</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpg()</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpg({'_', '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpg(Module)</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpg({Module, '_', '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpg(Module, Function)</name>
+ <fsummary>>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpg({Module, Function, '_'})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpg(Module, Function, Arity)</name>
+ <fsummary>>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>Same as ctpg({Module, Function, Arity})</p>
+ </desc>
+ </func>
+ <func>
+ <name>ctpg({Module, Function, Arity}) -> {ok, MatchDesc} | {error, term()}</name>
+ <fsummary>Clear call trace pattern for the specified functions</fsummary>
+ <desc>
+ <p>This function works as <c>ctp/1</c>, but only disables
+ tracing set up with <c>tp/2</c> (not with <c>tpl/2</c>).</p>
+ </desc>
+ </func>
+ <func>
+ <name>ltp() -> ok</name>
+ <fsummary>List saved and built-in match specifications on the console.</fsummary>
+ <desc>
+ <p>Use this function to recall all match specifications previously
+ used in the session (i. e. previously saved during calls
+ to <c>tp/2</c>, 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 <c>stop/0</c> 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 <c>wtp/1</c> and <c>rtp/1</c></p>
+ </desc>
+ </func>
+ <func>
+ <name>dtp() -> ok</name>
+ <fsummary>Delete all saved match specifications.</fsummary>
+ <desc>
+ <p>Use this function to "forget" all match specifications
+ saved during calls to <c>tp/2</c>.
+ This is useful when one wants to restore other match
+ specifications from a file with <c>rtp/1</c>. Use
+ <c>dtp/1</c> to delete specific saved match specifications. </p>
+ </desc>
+ </func>
+ <func>
+ <name>dtp(N) -> ok</name>
+ <fsummary>Delete a specific saved match_spec.</fsummary>
+ <type>
+ <v>N = integer()</v>
+ </type>
+ <desc>
+ <p>Use this function to "forget" a specific match specification
+ saved during calls to <c>tp/2</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>wtp(Name) -> ok | {error, IOError}</name>
+ <fsummary>Write all saved and built-in match specifications to a file</fsummary>
+ <type>
+ <v>Name = string()</v>
+ <v>IOError = term()</v>
+ </type>
+ <desc>
+ <p>This function will save all match specifications saved
+ during the session (during calls to <c>tp/2</c>)
+ and built-in match specifications in a text
+ file with the name designated by <c>Name</c>. The format
+ of the file is textual, why it can be edited with an
+ ordinary text editor, and then restored with
+ <c>rtp/1</c>. </p>
+ <p>Each match spec in the file ends with a full stop
+ (<c>.</c>) and new (syntactically correct) match
+ specifications can be added to the file manually.</p>
+ <p>The function returns <c>ok</c> or an error tuple where the
+ second element contains the I/O error that made the
+ writing impossible.</p>
+ </desc>
+ </func>
+ <func>
+ <name>rtp(Name) -> ok | {error, Error}</name>
+ <fsummary>Read saved match specifications from file.</fsummary>
+ <type>
+ <v>Name = string()</v>
+ <v>Error = term()</v>
+ </type>
+ <desc>
+ <p>This function reads match specifications from a file
+ (possibly) generated by the <c>wtp/1</c> 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 <em>merged</em>
+ with the current match specifications, so that no duplicates
+ are generated. Use <c>ltp/0</c> 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. <marker id="n"></marker>
+</p>
+ </desc>
+ </func>
+ <func>
+ <name>n(Nodename) -> {ok, Nodename} | {error, Reason}</name>
+ <fsummary>Add a remote node to the list of traced nodes</fsummary>
+ <type>
+ <v>Nodename = atom()</v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>The <c>dbg</c> server keeps a list of nodes where tracing
+ should be performed. Whenever a <c>tp/2</c> call or a
+ <c>p/2</c> call is made, it is executed for all nodes in this
+ list including the local node (except for <c>p/2</c> with a
+ specific <c>pid()</c> 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 (<c>Nodename</c>) 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 <c>no_local_tracer</c> is returned. The
+ tracer process on the local node must be started with the
+ <c>tracer/0/2</c> function.
+ </p>
+ <p>If <c>Nodename</c> is the local node, the error reason
+ <c>cant_add_local_node</c> is returned.
+ </p>
+ <p>If a trace port (<seealso marker="#trace_port">see</seealso><c>trace_port/2</c>) is
+ running on the local node, remote nodes can not be traced with
+ a tracer process. The error reason
+ <c>cant_trace_remote_pid_to_local_port</c> is returned. A
+ trace port can however be started on the remote node with the
+ <c>tracer/3</c> function.
+ </p>
+ <p>The function will also return an error if the node
+ <c>Nodename</c> is not reachable.</p>
+ </desc>
+ </func>
+ <func>
+ <name>cn(Nodename) -> ok</name>
+ <fsummary>Clear a node from the list of traced nodes.</fsummary>
+ <type>
+ <v>Nodename = atom()</v>
+ </type>
+ <desc>
+ <p>Clears a node from the list of traced nodes. Subsequent
+ calls to <c>tp/2</c> and <c>p/2</c> will not consider that
+ node, but tracing already activated on the node will continue
+ to be in effect.</p>
+ <p>Returns <c>ok</c>, cannot fail.</p>
+ </desc>
+ </func>
+ <func>
+ <name>ln() -> ok</name>
+ <fsummary>Show the list of traced nodes on the console.</fsummary>
+ <desc>
+ <p>Shows the list of traced nodes on the console.</p>
+ </desc>
+ </func>
+ <func>
+ <name>tracer() -> {ok, pid()} | {error, already_started}</name>
+ <fsummary>Start a tracer server that handles trace messages.</fsummary>
+ <desc>
+ <p>This function starts a server on the local node that will
+ be the recipient of all trace messages. All subsequent calls
+ to <c>p/2</c> 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 <c>tracer/2</c> for a description
+ of how the trace message handler can be customized. <marker id="tracer2"></marker>
+</p>
+ <p>To start a similar tracer on a remote node, use <c>n/1</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>tracer(Type, Data) -> {ok, pid()} | {error, Error}</name>
+ <fsummary>Start a tracer server with additional parameters</fsummary>
+ <type>
+ <v>Type = port | process</v>
+ <v>Data = PortGenerator | HandlerSpec</v>
+ <v>HandlerSpec = {HandlerFun, InitialData}</v>
+ <v>HandlerFun = fun() (two arguments)</v>
+ <v>InitialData = term()</v>
+ <v>PortGenerator = fun() (no arguments)</v>
+ <v>Error = term()</v>
+ </type>
+ <desc>
+ <p>This function starts a tracer server with additional
+ parameters on the local node. The first parameter, the
+ <c>Type</c>, indicates if trace messages should be handled
+ by a receiving process (<c>process</c>) or by a tracer port
+ (<c>port</c>). For a description about tracer ports see
+ <c>trace_port/2</c>.
+ </p>
+ <p>If <c>Type</c> is a process, a message handler function can
+ be specified (<c>HandlerSpec</c>). The handler function, which
+ should be a <c>fun</c> 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 <c>InitialData</c>
+ part of the <c>HandlerSpec</c>. The <c>HandlerFun</c> may
+ chose any appropriate action to take when invoked, and can
+ save a state for the next invocation by returning it.
+ </p>
+ <p>If <c>Type</c> is a port, then the second parameter should
+ be a <em>fun</em> which takes no arguments and returns a
+ newly opened trace port when called. Such a <em>fun</em> is
+ preferably generated by calling <c>trace_port/2</c>.
+ </p>
+ <p>If an error is returned, it can either be due to a tracer
+ server already running (<c>{error,already_started}</c>) or
+ due to the <c>HandlerFun</c> throwing an exception.
+ </p>
+ <p>To start a similar tracer on a remote node, use
+ <c>tracer/3</c>. <marker id="trace_port"></marker>
+</p>
+ </desc>
+ </func>
+ <func>
+ <name>tracer(Nodename, Type, Data) -> {ok, Nodename} | {error, Reason}</name>
+ <fsummary>Start a tracer server on given node with additional parameters</fsummary>
+ <type>
+ <v>Nodename = atom()</v>
+ </type>
+ <desc>
+ <p>This function is equivalent to <c>tracer/2</c>, but acts on
+ the given node. A tracer is started on the node
+ (<c>Nodename</c>) and the node is added to the list of traced
+ nodes.
+ </p>
+ <note>
+ <p>This function is not equivalent to <c>n/1</c>. While
+ <c>n/1</c> starts a process tracer which redirects all trace
+ information to a process tracer on the local node (i.e. the
+ trace control node), <c>tracer/3</c> starts a tracer of any
+ type which is independent of the tracer on the trace control
+ node.</p>
+ </note>
+ <p>For details, <seealso marker="#tracer2">see</seealso><c>tracer/2</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>trace_port(Type, Parameters) -> fun()</name>
+ <fsummary>Create and returns a trace port generating<em>fun</em></fsummary>
+ <type>
+ <v>Type = ip | file</v>
+ <v>Parameters = Filename | WrapFilesSpec | IPPortSpec</v>
+ <v>Filename = string() | [string()] | atom()</v>
+ <v>WrapFilesSpec = {Filename, wrap, Suffix} | {Filename, wrap, Suffix, WrapSize} | {Filename, wrap, Suffix, WrapSize, WrapCnt}</v>
+ <v>Suffix = string()</v>
+ <v>WrapSize = integer() >= 0 | {time, WrapTime}</v>
+ <v>WrapTime = integer() >= 1</v>
+ <v>WrapCnt = integer() >= 1</v>
+ <v>IpPortSpec = PortNumber | {PortNumber, QueSize}</v>
+ <v>PortNumber = integer()</v>
+ <v>QueSize = integer()</v>
+ </type>
+ <desc>
+ <p>This function creates a trace port generating <em>fun</em>.
+ The <em>fun</em> 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. <c>dbg:tracer(port, dbg:trace_port(ip, 4711))</c>. </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
+ <c>file</c> and the <c>ip</c> 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
+ <c>trace_client/2</c> function. The ip driver opens a TCP/IP
+ port where it listens for connections. When a client
+ (preferably started by calling <c>trace_client/2</c> 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 <em>not</em>
+ 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 <c>Filename ++ SeqCnt ++ Suffix</c>, where <c>SeqCnt</c> counts as a decimal string
+ from <c>0</c> to <c>WrapCnt</c> and then around again from
+ <c>0</c>. When a trace term written to
+ the current file makes it longer than <c>WrapSize</c>,
+ that file is closed, if the number of files in this
+ wrap trace is as many as <c>WrapCnt</c> 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
+ <c>WrapCnt</c> trace files saved with a size of at least
+ <c>WrapSize</c> (but not much bigger), except for
+ the last file that might even be empty. The default values
+ are <c>WrapSize = 128*1024</c> and <c>WrapCnt = 8</c>.</p>
+ <p>The <c>SeqCnt</c> values in the filenames are all in the
+ range <c>0</c> through <c>WrapCnt</c> with a gap in the
+ circular sequence. The gap is needed to find the end of the
+ trace.</p>
+ <p>If the <c>WrapSize</c> is specified as
+ <c>{time, WrapTime}</c>, the current file is closed when it
+ has been open more than <c>WrapTime</c> milliseconds,
+ regardless of it being empty or not.</p>
+ <p>The ip trace driver has a queue of <c>QueSize</c> 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 <c>trace_client/3</c> as the tuple <c>{drop, N}</c> where <c>N</c> 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>
+ </desc>
+ </func>
+ <func>
+ <name>flush_trace_port()</name>
+ <fsummary>Equivalent to flush_trace_port(node()).</fsummary>
+ <desc>
+ <p>Equivalent to <c>flush_trace_port(node())</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>flush_trace_port(Nodename) -> ok | {error, Reason}</name>
+ <fsummary>Flush internal data buffers in a trace driver on the given node.</fsummary>
+ <desc>
+ <p>Equivalent to <c>trace_port_control(Nodename,flush)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>trace_port_control(Operation)</name>
+ <fsummary>Equivalent to trace_port_control(node(),Operation).</fsummary>
+ <desc>
+ <p>Equivalent to <c>trace_port_control(node(),Operation)</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>trace_port_control(Nodename,Operation) -> ok | {ok, Result} | {error, Reason}</name>
+ <fsummary>Perform a control operation on the active trace port driver on the given node.</fsummary>
+ <type>
+ <v>Nodename = atom()</v>
+ </type>
+ <desc>
+ <p>This function is used to do a control operation on the
+ active trace port driver on the given node
+ (<c>Nodename</c>). Which operations that are allowed as well
+ as their return values are depending on which trace driver
+ that is used.</p>
+ <p>Returns either <c>ok</c> or <c>{ok, Result}</c>
+ if the operation was successful, or <c>{error, Reason}</c>
+ if the current tracer is a process
+ or if it is a port not supporting the operation.</p>
+ <p>The allowed values for <c>Operation</c> are:</p>
+ <taglist>
+ <tag><c>flush</c></tag>
+ <item>
+ <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 <c>ok</c>.</p>
+ </item>
+ <tag><c>get_listen_port</c></tag>
+ <item>
+ <p>Returns <c>{ok, IpPort}</c> where <c>IpPort</c>is
+ the IP port number used by the driver listen socket.
+ Only the ip trace driver supports this operation.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+ <func>
+ <name>trace_client(Type, Parameters) -> pid()</name>
+ <fsummary>Start a trace client that reads messages created by a trace port driver</fsummary>
+ <type>
+ <v>Type = ip | file | follow_file</v>
+ <v>Parameters = Filename | WrapFilesSpec | IPClientPortSpec</v>
+ <v>Filename = string() | [string()] | atom()</v>
+ <v>WrapFilesSpec = see trace_port/2</v>
+ <v>Suffix = string()</v>
+ <v>IpClientPortSpec = PortNumber | {Hostname, PortNumber}</v>
+ <v>PortNumber = integer()</v>
+ <v>Hostname = string()</v>
+ </type>
+ <desc>
+ <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 <c>tracer/0</c>
+ function.</p>
+ <p>If <c>Type</c> is <c>file</c>, the client reads all trace
+ messages stored in the file named <c>Filename</c> or
+ specified by <c>WrapFilesSpec</c> (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 <c>Type</c> is <c>follow_file</c>, the client behaves as
+ in the <c>file</c> case, but keeps trying to read (and
+ process) more data
+ from the file until stopped by <c>stop_trace_client/1</c>.
+ <c>WrapFilesSpec</c> is not allowed as second argument
+ for this <c>Type</c>.</p>
+ <p>If <c>Type</c> is <c>ip</c>, the client connects to the
+ TCP/IP port <c>PortNumber</c> on the host <c>Hostname</c>,
+ from where it reads trace messages until the TCP/IP connection
+ is closed. If no <c>Hostname</c> 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 <em>not</em>
+ distributed), where the formatting occurs:</p>
+ <p>On the node <c>stack</c> there's an Erlang node
+ <c>ant@stack</c>, in the shell, type the following:</p>
+ <pre>
+ant@stack> <input>dbg:tracer(port, dbg:trace_port(ip,4711)).</input>
+&lt;0.17.0>
+ant@stack> <input>dbg:p(self(), send).</input>
+{ok,1}</pre>
+ <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>
+ <pre>
+-> <input>dbg:trace_client(ip, {"stack", 4711}).</input>
+&lt;0.42.0></pre>
+ <p>If we now send a message from the shell on the node
+ <c>ant@stack</c>, where all sends from the shell are traced:</p>
+ <pre>
+ant@stack> <input>self() ! hello.</input>
+hello</pre>
+ <p>The following will appear at the console on the node that
+ started the trace client:</p>
+ <pre>
+(&lt;0.23.0>) &lt;0.23.0> ! hello
+(&lt;0.23.0>) &lt;0.22.0> ! {shell_rep,&lt;0.23.0>,{value,hello,[],[]}}</pre>
+ <p>The last line is generated due to internal message passing
+ in the Erlang shell. The process id's will vary.</p>
+ </desc>
+ </func>
+ <func>
+ <name>trace_client(Type, Parameters, HandlerSpec) -> pid()</name>
+ <fsummary>Start a trace client that reads messages created by a trace port driver, with a user defined handler</fsummary>
+ <type>
+ <v>Type = ip | file | follow_file</v>
+ <v>Parameters = Filename | WrapFilesSpec | IPClientPortSpec</v>
+ <v>Filename = string() | [string()] | atom()</v>
+ <v>WrapFilesSpec = see trace_port/2</v>
+ <v>Suffix = string()</v>
+ <v>IpClientPortSpec = PortNumber | {Hostname, PortNumber}</v>
+ <v>PortNumber = integer()</v>
+ <v>Hostname = string()</v>
+ <v>HandlerSpec = {HandlerFun, InitialData}</v>
+ <v>HandlerFun = fun() (two arguments)</v>
+ <v>InitialData = term()</v>
+ </type>
+ <desc>
+ <p>This function works exactly as <c>trace_client/2</c>, but
+ allows you to write your own handler function. The handler
+ function works mostly as the one described in
+ <c>tracer/2</c>, but will also have to be prepared to handle
+ trace messages of the form <c>{drop, N}</c>, where <c>N</c> 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 <c>file</c>, the pseudo trace message
+ <c>end_of_trace</c> will appear at the end of the trace. The
+ return value from the handler function is in this case
+ ignored.</p>
+ </desc>
+ </func>
+ <func>
+ <name>stop_trace_client(Pid) -> ok</name>
+ <fsummary>Stop a trace client gracefully.</fsummary>
+ <type>
+ <v>Pid = pid()</v>
+ </type>
+ <desc>
+ <p>This function shuts down a previously started trace
+ client. The <c>Pid</c> argument is the process id returned
+ from the <c>trace_client/2</c> or <c>trace_client/3</c> call.</p>
+ </desc>
+ </func>
+ <func>
+ <name>get_tracer()</name>
+ <fsummary>Equivalent to get_tracer(node()).</fsummary>
+ <desc>
+ <p>Equivalent to <c>get_tracer(node())</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name>get_tracer(Nodename) -> {ok, Tracer}</name>
+ <fsummary>Return the process or port to which all trace messages are sent.</fsummary>
+ <type>
+ <v>Nodename = atom()</v>
+ <v>Tracer = port() | pid()</v>
+ </type>
+ <desc>
+ <p>Returns the process or port to which all trace
+ messages are sent. </p>
+ </desc>
+ </func>
+ <func>
+ <name>stop() -> stopped</name>
+ <fsummary>Stop the <c>dbg</c>server and the tracing of all processes.</fsummary>
+ <desc>
+ <p>Stops the <c>dbg</c> 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>
+ </desc>
+ </func>
+ <func>
+ <name>stop_clear() -> stopped</name>
+ <fsummary>Stop the <c>dbg</c>server and the tracing of all processes, and clears trace patterns.</fsummary>
+ <desc>
+ <p>Same as stop/0, but also clears all trace patterns on local
+ and global functions calls.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="simple_example"></marker>
+ <title>Simple examples - tracing from the shell</title>
+ <p>The simplest way of tracing from the Erlang shell is to use
+ <c>dbg:c/3</c> or <c>dbg:c/4</c>, e.g. tracing the function
+ <c>dbg:get_tracer/0</c>:</p>
+ <pre>
+(tiger@durin)84> <input>dbg:c(dbg,get_tracer,[]).</input>
+(&lt;0.154.0>) &lt;0.152.0> ! {&lt;0.154.0>,{get_tracer,tiger@durin}}
+(&lt;0.154.0>) out {dbg,req,1}
+(&lt;0.154.0>) &lt;&lt; {dbg,{ok,&lt;0.153.0>}}
+(&lt;0.154.0>) in {dbg,req,1}
+(&lt;0.154.0>) &lt;&lt; timeout
+{ok,&lt;0.153.0>}
+(tiger@durin)85></pre>
+ <p>Another way of tracing from the shell is to explicitly start a
+ <em>tracer</em> and then set the <em>trace flags</em> of your
+ choice on the processes you want to trace, e.g. trace messages and
+ process events:</p>
+ <pre>
+(tiger@durin)66> <input>Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).</input>
+&lt;0.126.0>
+(tiger@durin)67> <input>dbg:tracer().</input>
+{ok,&lt;0.128.0>}
+(tiger@durin)68> <input>dbg:p(Pid,[m,procs]).</input>
+{ok,[{matched,tiger@durin,1}]}
+(tiger@durin)69> <input>Pid ! {self(),hello}.</input>
+(&lt;0.126.0>) &lt;&lt; {&lt;0.116.0>,hello}
+{&lt;0.116.0>,hello}
+(&lt;0.126.0>) &lt;&lt; timeout
+(&lt;0.126.0>) &lt;0.116.0> ! hello
+(&lt;0.126.0>) exit normal
+(tiger@durin)70> <input>flush().</input>
+Shell got hello
+ok
+(tiger@durin)71></pre>
+ <p>If you set the <c>call</c> trace flag, you also have to set a
+ <em>trace pattern</em> for the functions you want to trace:</p>
+ <pre>
+(tiger@durin)77> <input>dbg:tracer().</input>
+{ok,&lt;0.142.0>}
+(tiger@durin)78> <input>dbg:p(all,call).</input>
+{ok,[{matched,tiger@durin,3}]}
+(tiger@durin)79> <input>dbg:tp(dbg,get_tracer,0,[]).</input>
+{ok,[{matched,tiger@durin,1}]}
+(tiger@durin)80> <input>dbg:get_tracer().</input>
+(&lt;0.116.0>) call dbg:get_tracer()
+{ok,&lt;0.143.0>}
+(tiger@durin)81> <input>dbg:tp(dbg,get_tracer,0,[{'_',[],[{return_trace}]}]).</input>
+{ok,[{matched,tiger@durin,1},{saved,1}]}
+(tiger@durin)82> <input>dbg:get_tracer().</input>
+(&lt;0.116.0>) call dbg:get_tracer()
+(&lt;0.116.0>) returned from dbg:get_tracer/0 -> {ok,&lt;0.143.0>}
+{ok,&lt;0.143.0>}
+(tiger@durin)83></pre>
+ </section>
+
+ <section>
+ <marker id="advanced"></marker>
+ <title>Advanced topics - combining with seq_trace</title>
+ <p>The <c>dbg</c> module is primarily targeted towards
+ tracing through the <c>erlang:trace/3</c> function. It is
+ sometimes desired to trace messages in a more delicate way, which
+ can be done with the help of the <c>seq_trace</c> module.
+ </p>
+ <p><c>seq_trace</c> implements sequential tracing (known in the
+ AXE10 world, and sometimes called "forlopp tracing"). <c>dbg</c>
+ can interpret messages generated from <c>seq_trace</c> and the
+ same tracer function for both types of tracing can be used. The
+ <c>seq_trace</c> 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 <c>dbg</c> and <c>seq_trace</c> can be quite
+ powerful. This brief example shows a session where sequential
+ tracing is used:</p>
+ <pre>
+1> <input>dbg:tracer().</input>
+{ok,&lt;0.30.0>}
+2> <input>{ok, Tracer} = dbg:get_tracer().</input>
+{ok,&lt;0.31.0>}
+3> <input>seq_trace:set_system_tracer(Tracer).</input>
+false
+4> <input>dbg:tp(dbg, get_tracer, 0, [{[],[],[{set_seq_token, send, true}]}]).</input>
+{ok,[{matched,nonode@nohost,1},{saved,1}]}
+5> <input>dbg:p(all,call).</input>
+{ok,[{matched,nonode@nohost,22}]}
+6> <input>dbg:get_tracer(), seq_trace:set_token([]).</input>
+(&lt;0.25.0>) call dbg:get_tracer()
+SeqTrace [0]: (&lt;0.25.0>) &lt;0.30.0> ! {&lt;0.25.0>,get_tracer} [Serial: {2,4}]
+SeqTrace [0]: (&lt;0.30.0>) &lt;0.25.0> ! {dbg,{ok,&lt;0.31.0>}} [Serial: {4,5}]
+{1,0,5,&lt;0.30.0>,4}</pre>
+ <p>This session sets the system_tracer to the same process as
+ the ordinary tracer process (i. e. &lt;0.31.0&gt;) and sets the
+ trace pattern for the function <c>dbg:get_tracer</c> 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
+ <c>seq_trace</c> messages are sent both for the server request
+ and the response. The <c>seq_trace:set_token([])</c> after the
+ call clears the <c>seq_trace</c> 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>
+ </section>
+
+ <section>
+ <title>Note of caution</title>
+ <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 <c>io</c> function such as <c>format/2</c>. Note that when
+ <c>dbg:p(all,call)</c> is called, IO processes are also traced.
+ Here's an example:</p>
+ <pre>
+%% Using a default line editing shell
+1> <input>dbg:tracer(process, {fun(Msg,_) -> io:format("~p~n", [Msg]), 0 end, 0}).</input>
+{ok,&lt;0.37.0>}
+2> <input>dbg:p(all, [call]).</input>
+{ok,[{matched,nonode@nohost,25}]}
+3> <input>dbg:tp(mymod,[{'_',[],[]}]).</input>
+{ok,[{matched,nonode@nohost,0},{saved,1}]}
+4> <input>mymod:</input> % TAB pressed here
+%% -- Deadlock --</pre>
+ <p>Here's another example:</p>
+ <pre>
+%% Using a shell without line editing (oldshell)
+1> <input>dbg:tracer(process).</input>
+{ok,&lt;0.31.0>}
+2> <input>dbg:p(all, [call]).</input>
+{ok,[{matched,nonode@nohost,25}]}
+3> <input>dbg:tp(lists,[{'_',[],[]}]).</input>
+{ok,[{matched,nonode@nohost,0},{saved,1}]}
+% -- Deadlock --</pre>
+ <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
+ <c>mymod:module_info()</c>. This generates a trace message which, in turn, causes the
+ tracer process to send an IO request to the group leader (by calling <c>io:format/2</c>).
+ 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 <c>user</c> process. When Erlang is
+ started in oldshell mode, the shell process will have <c>user</c> as its
+ group leader and so will the tracer process in this example. Since <c>user</c> calls
+ functions in <c>lists</c> 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>
+ <list type="bulleted">
+ <item>Don't trace the group leader of the tracer process. If tracing has been switched on
+ for all processes, call <c>dbg:p(TracerGLPid,clear)</c> to stop tracing the group leader
+ (<c>TracerGLPid</c>). <c>process_info(TracerPid,group_leader)</c> tells you
+ which process this is (<c>TracerPid</c> is returned from <c>dbg:get_tracer/0</c>).</item>
+ <item>Don't trace the <c>user</c> process if using the default trace handler function.</item>
+ <item>In your own trace handler function, call <c>erlang:display/1</c> instead of an
+ <c>io</c> function or, if <c>user</c> is not used as group leader, print to
+ <c>user</c> instead of the default group leader. Example:
+ <c>io:format(user,Str,Args)</c>.</item>
+ </list>
+ </section>
+</erlref>
+