<html>
<body>
<div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
<table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
<tr>
<td>
This is an automatically generated e-mail. To reply, visit:
<a href="https://reviewboard.asterisk.org/r/3752/">https://reviewboard.asterisk.org/r/3752/</a>
</td>
</tr>
</table>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On July 11th, 2014, 10:01 p.m. CDT, <b>Corey Farrell</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="https://reviewboard.asterisk.org/r/3752/diff/1/?file=62839#file62839line503" style="color: black; font-weight: bold; text-decoration: underline;">/team/group/media_formats-reviewed-trunk/main/astobj2.c</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#e9eaa8" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2">502</font></th>
<td bgcolor="#fdfebc" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="k">if</span> <span class="p">(</span><span class="n">ref_log</span> <span class="o">&&</span> <span class="n">user_data</span><span class="p">)</span> <span class="p">{</span></pre></td>
<th bgcolor="#e9eaa8" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">503</font></th>
<td bgcolor="#fdfebc" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="k">if</span> <span class="p">(</span><span class="n">obj</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span></pre></td>
</tr>
<tr>
<th bgcolor="#e9eaa8" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2">503</font></th>
<td bgcolor="#fdfebc" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="tb"> </span><span class="k">if</span> <span class="p">(</span><span class="n">obj</span> <span class="o">&&</span> <span class="n">obj</span><span class="o">-></span><span class="n">priv_data</span><span class="p">.</span><span class="n">ref_counter</span> <span class="o">+</span> <span class="n">delta</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span></pre></td>
<th bgcolor="#e9eaa8" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">504</font></th>
<td bgcolor="#fdfebc" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="tb"> </span><span class="n">ast_log_backtrace</span><span class="p">();</span></pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">505</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="tb"> </span><span class="n">ast_assert</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span></pre></td>
</tr>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">506</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="tb"> </span><span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span></pre></td>
</tr>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">507</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="p">}</span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">This reorder will prevent ref_log from recording a double-free.
Example:
obj = ao2_alloc(..);
ao2_ref(obj, -1);
ao2_ref(obj, -1);
Currently this block of code would produce an error in the ref_log.
Also I know it sounds weird but I've seen:
Thread 1: ao2_ref(obj, -1) == 2
Thread 2: ao2_ref(obj, -1) == 1
And for thread 2 (which runs the destructor) actually finishing first (and the last 2 entries to ref_log are reversed.</pre>
</blockquote>
<p>On July 11th, 2014, 10:07 p.m. CDT, <b>Matt Jordan</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">I'm not sure either of those are worth not fixing this:
(1) A double free is highly likely to crash immediately, in which case, the ref debug log is only so useful. Plus, in a double free, you typically have the memory address that is now hostile, which can be correlated back to a ref debug log.
(2) The out of order printing of destruction is possible, but is handled by the refcounter script since it looks for the destructor message (and will now actually get it)
With the current code, we can get an admittedly large number of false positives, which isn't super useful.</pre>
</blockquote>
<p>On July 11th, 2014, 10:16 p.m. CDT, <b>Corey Farrell</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">The out of order destruction printing is actually worse with this update. It causes the destructor to be 2nd to last, then the last entry is unref from 2. This last entry appears as a skew and leak, separate from the rest of the history for that object. So we will still get the same false positive, but in this case we'll be able to see the history of refs to know that it's a false positive.</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">I do think that this could cause the destructor message to get printed earlier slightly more often, although the testing I've done so far hasn't shown that we get considerably more 'skewed' results than we did of incorrectly reported leaked objects.
Regardless, I still think this is, in the long run, better.
(1) Generally, ref count debugging is used to find ref leaks. Having an erroneously report of a leak is more detrimental to the primary purpose of ref_debug than an incorrectly reported skewed object.
(2) The script *could* be modified to work around the out of order destruction message. The script could be made to look at the reported ref count of the object (since that value will now be accurate) and build out the full history of the object. Only when the object's history is fully built, *and* we get a destruction message, would it then print and dispose of the object. This would fix the falsely reported skewed objects in the script. Contrary to this, without this patch, it would be very difficult to fix inaccurate reporting of leaked objects in the script. (a) You don't get an indication that the object was destroyed, and (b) The reference count reported in the messages is false.
(3) Skewed objects are generally a reflection of a coding error in astobj2 and nothing else. For example, a framework that uses astobj2 should not be able to create an object with an initial reference count of 3. If an object is skewed, it's because it 'showed up' in the log with no constructor and with an unexpected reference count; generally, that would mean that something managed to bypass astobj's ref_debug printing. That typically only occurs when internal nodes in astobj2 incorrectly manipulate the ref functions themselves. As such, having misreported skewed objects is generally less harmful (and can also be suppressed) than misreported leaked objects.
Finally, we have a race condition (one that I admittedly caused!) Disregarding the printing of the destruction message, we have an atomic integer value that is wrongly reported without this patch. We could make ref_debug more complex here to truly "solve" the race between threads destroying an object and the reporting; however, there is limited bang for the buck.
- A global lock would cripple the system and/or render ref_debug useless
- A thread safe queue that enqueues messages to another thread for processing is generally equivalent to a global lock
I'd prefer to make the post-processing 'smarter', and make the ref counts reported accurate.</pre>
<br />
<p>- Matt</p>
<br />
<p>On July 11th, 2014, 9:45 p.m. CDT, Matt Jordan wrote:</p>
<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('https://reviewboard.asterisk.org/static/rb/images/review_request_box_top_bg.ab6f3b1072c9.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
<tr>
<td>
<div>Review request for Asterisk Developers and Corey Farrell.</div>
<div>By Matt Jordan.</div>
<p style="color: grey;"><i>Updated July 11, 2014, 9:45 p.m.</i></p>
<div style="margin-top: 1.5em;">
<b style="color: #575012; font-size: 10pt;">Repository: </b>
Asterisk
</div>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
<tr>
<td>
<pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">As Corey noticed, when an object's reference is changed rapidly the ref debug log will report the wrong reference. This is due to accessing the reference (which is not thread safe) prior to the reference count being changed. Since the change in reference count is returned by internal_ao2_ref, it can be used instead to determine what the current state of the object is.</pre>
</td>
</tr>
</table>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
<tr>
<td>
<pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Objects that were incorrectly reported as leaked no longer are.</pre>
</td>
</tr>
</table>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">
<li>/team/group/media_formats-reviewed-trunk/main/astobj2.c <span style="color: grey">(418435)</span></li>
</ul>
<p><a href="https://reviewboard.asterisk.org/r/3752/diff/" style="margin-left: 3em;">View Diff</a></p>
</td>
</tr>
</table>
</div>
</body>
</html>