<html>
<head>
<base href="https://wiki.asterisk.org/wiki">
<link rel="stylesheet" href="/wiki/s/en/2176/25/9/_/styles/combined.css?spaceKey=AST&forWysiwyg=true" type="text/css">
</head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
<h2><a href="https://wiki.asterisk.org/wiki/display/AST/Reference+Count+Debugging">Reference Count Debugging</a></h2>
<h4>Page <b>added</b> by <a href="https://wiki.asterisk.org/wiki/display/~mjordan">Matt Jordan</a>
</h4>
<br/>
<div class="notificationGreySide">
<h1><a name="ReferenceCountDebugging-EnablingReferenceCountLogs"></a>Enabling Reference Count Logs</h1>
<p>Asterisk makes extensive use of reference counted objects using the <tt>astobj2</tt> API. In certain classes of bugs, the reference count for an object may get erroneously increased - leading to an object never getting reclaimed when its lifetime has ended - or decreased - leading (in the best case) to <tt>ERROR</tt> messages being reported that a bad magic number has been detected or (in the worse case) invalid memory deallocation.</p>
<p>In such cases, its often very useful to determine what in Asterisk manipulated the reference count on the object. The <tt>astobj2</tt> API supports creating a reference count log for all objects managed by the API. The log is always created as <tt>/tmp/refs</tt>.</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>NOTICE</b><br />This option is not available via <tt>menuselect</tt>. It can only be enabled by defining compile time options directly in Asterisk. Do not attempt to do this if you do not feel comfortable manipulating the Asterisk source.</td></tr></table></div>
<p>When enabling reference count debugging, you can either attempt to enable it for all users of the <tt>astobj2</tt> API, or for individual files that use the <tt>astobj2</tt> API. In general, its recommended that you only enable ref count debugging in the specific files that use the <tt>astobj2</tt> API, as enabling it for all users will result in a very large <tt>/tmp/refs</tt> file very quickly.</p>
<h5><a name="ReferenceCountDebugging-EnablingReferenceCountDebuggingforaSpecificModule"></a>Enabling Reference Count Debugging for a Specific Module</h5>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>NOTICE</b><br />This procedure assumes that you will be enabling reference count debugging in <tt>chan_sip</tt>. Other modules may differ slightly.</td></tr></table></div>
<ol>
        <li>Locate the include directive for <tt>asterisk.h</tt> in your module and the definition of the <tt>ASTERISK_FILE_VERSION</tt>.
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision: XXXXXX $")</pre>
</div></div></li>
        <li>After the include directive for <tt>asterisk.h</tt>, <b>but before</b> the inclusion of <tt>astobj2.h</tt>, insert the following:
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision: XXXXXX $")
/* INSERTED */
#define REF_DEBUG 1
/* END INSERTED */</pre>
</div></div></li>
        <li>Note that <tt>chan_sip</tt> already has a comment denoting the proper place to define <tt>REF_DEBUG</tt>. This will look something like the following:
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision: 372763 $")
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
#include <inttypes.h>
#include "asterisk/network.h"
#include "asterisk/paths.h"        /* need ast_config_AST_SYSTEM_NAME */
/*
Uncomment the define below, if you are having refcount related memory leaks.
With this uncommented, this module will generate a file, /tmp/refs, which contains
a history of the ao2_ref() calls. To be useful, all calls to ao2_* functions should
be modified to ao2_t_* calls, and include a tag describing what is happening with
enough detail, to make pairing up a reference count increment with its corresponding decrement.
The refcounter program in utils/ can be invaluable in highlighting objects that are not
balanced, along with the complete history for that object.
In normal operation, the macros defined will throw away the tags, so they do not
affect the speed of the program at all. They can be considered to be documentation.
*/
#define REF_DEBUG 1
#include "asterisk/lock.h"</pre>
</div></div></li>
        <li>Re-compile Asterisk and re-install. Assuming the account Asterisk runs under has sufficient permissions to write to the <tt>/tmp</tt> folder, a <tt>/tmp/refs</tt> file should be created containing the reference counts for <tt>chan_sip</tt>.</li>
</ol>
<h5><a name="ReferenceCountDebugging-EnablingReferenceCountDebuggingforallModules"></a>Enabling Reference Count Debugging for all Modules</h5>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>NOTICE</b><br />This procedure assumes you want to track <b>all</b> reference counted objects in Asterisk. This is expensive and liable to create a very large reference counting log in <tt>/tmp/refs</tt>.</td></tr></table></div>
<ol>
        <li>Open <tt>astobj2.h</tt> in <tt>include/asterisk</tt>.</li>
        <li>Locate the header guard definition for the header file. Below it, define the <tt>REF_DEBUG</tt> option.
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Confluence; brush: c; gutter: false">#ifndef _ASTERISK_ASTOBJ2_H
#define _ASTERISK_ASTOBJ2_H
#undef REF_DEBUG
#define REF_DEBUG 1</pre>
</div></div></li>
        <li>Re-compile Asterisk and re-install. Assuming the account Asterisk runs under has sufficient permissions to write to the <tt>/tmp</tt> folder, a <tt>/tmp/refs</tt> file should be created containing the reference counts for all modules in Asterisk.</li>
</ol>
<h1><a name="ReferenceCountDebugging-InterpretingaReferenceCountLog"></a>Interpreting a Reference Count Log</h1>
<p>Each change in the reference count value of an <tt>ao2</tt> object will generate at least one line of output in <tt>/tmp/refs</tt>. This will look something like the following:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>...
0x8756f00 =1 chan_sip.c:22240:load_module (allocate users)
0x86e3408 =1 chan_sip.c:22241:load_module (allocate peers)
0x86dd380 =1 chan_sip.c:22242:load_module (allocate peers_by_ip)
0x822d020 =1 chan_sip.c:22243:load_module (allocate dialogs)
0x8930fd8 =1 chan_sip.c:20025:build_peer (allocate a peer struct)
0x8930fd8 +1 chan_sip.c:21467:reload_config (link peer into peer table) [@1]
0x8930fd8 -1 chan_sip.c:2370:unref_peer (unref_peer: from reload_config) [@2]
0x89318b0 =1 chan_sip.c:20025:build_peer (allocate a peer struct)
0x89318b0 +1 chan_sip.c:21467:reload_config (link peer into peer table) [@1]
0x89318b0 -1 chan_sip.c:2370:unref_peer (unref_peer: from reload_config) [@2]
0x8930218 =1 chan_sip.c:20025:build_peer (allocate a peer struct)
0x8930218 +1 chan_sip.c:21539:reload_config (link peer into peers table) [@1]
0x868c040 -1 chan_sip.c:2424:dialog_unlink_all (unset the relatedpeer->call field in tandem with relatedpeer field itself) [@2]
0x868c040 -1 chan_sip.c:2443:dialog_unlink_all (Let's unbump the count in the unlink so the poor pvt can disappear if it is time) [@1]
0x868c040 **call destructor** chan_sip.c:2443:dialog_unlink_all (Let's unbump the count in the unlink so the poor pvt can disappear if it is time)
0x8cc07e8 -1 chan_sip.c:2370:unref_peer (unsetting a dialog relatedpeer field in sip_destroy) [@3]
0x8cc07e8 +1 chan_sip.c:3876:find_peer (ao2_find in peers table) [@2]
0x8cc07e8 -1 chan_sip.c:2370:unref_peer (unref_peer, from sip_devicestate, release ref from find_peer) [@3]
...
</pre>
</div></div>
<ul>
        <li>The first column is the object address.</li>
        <li>The second column reflects how the operation affected the ref count for that object.
        <ul>
                <li>Creation sets the ref count to 1 (=1).</li>
                <li>Increment or decrement and the amount are specified by (-1/+1).</li>
                <li>The **call destructor** is specified by the <tt>astobj2</tt> API itself when the destroy routine is run for an object. It does not affect the ref count, but is important in debugging.</li>
        </ul>
        </li>
        <li>The third column specifies where in a given file the reference count change was made, the function name, and - if applicable - a descriptive tag supplied in the function call.</li>
        <li>If the reference count changed, the previous reference count is appended to the end of the line, e.g., <tt>[@1]</tt> indicates that the previous reference count was 1.</li>
</ul>
<p>When you have a generated <tt>/tmp/refs</tt> file, you can "<tt>sort -s -k 1 /tmp/refs > x1</tt>" to get a sorted list of all the objects, or you can use "utils/refcounter" application provided with Asterisk to scan the file for you and output any problems it finds.</p>
</div>
<div id="commentsSection" class="wiki-content pageSection">
<div style="float: right;" class="grey">
<a href="https://wiki.asterisk.org/wiki/users/removespacenotification.action?spaceKey=AST">Stop watching space</a>
<span style="padding: 0px 5px;">|</span>
<a href="https://wiki.asterisk.org/wiki/users/editmyemailsettings.action">Change email notification preferences</a>
</div>
<a href="https://wiki.asterisk.org/wiki/display/AST/Reference+Count+Debugging">View Online</a>
|
<a href="https://wiki.asterisk.org/wiki/display/AST/Reference+Count+Debugging?showComments=true&showCommentArea=true#addcomment">Add Comment</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>