<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/3402/">https://reviewboard.asterisk.org/r/3402/</a>
</td>
</tr>
</table>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On March 26th, 2014, 3:38 p.m. CDT, <b>Matt Jordan</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/3402/diff/1/?file=56722#file56722line472" style="color: black; font-weight: bold; text-decoration: underline;">/branches/12/main/http.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; ">void ast_http_send(struct ast_tcptls_session_instance *ser,</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">472</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="tb"> </span><span class="n">shutdown</span><span class="p">(</span><span class="n">ser</span><span class="o">-></span><span class="n">fd</span><span class="p">,</span> <span class="mi">1</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;">I'm not sure why the send-only shutdown of ser->fd is needed here.
When the file stream is closed via fclose(ser->f), the file descriptor is implicitly closed as well.
>From http://linux.die.net/man/3/fdopen:
"The file descriptor is not dup'ed, and will be closed when the stream created by fdopen() is closed."
I'm not sure why the fflush is strictly necessary here as well, as closing should flush the file stream.</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;">This is strictly a workaround for what I presume to be a bug in the socket/tcp buffer handling (i.e. linux kernel). In my testing, a low level write() to ser->fd resulted in the same exact failure scenario: data was written to the socket just prior to close that did not end up being transmitted by TCP -- but only when Asterisk is running in a VM; and further only when the far end of the socket originates from a machine other than that same vm.
Thus: I don't believe fdopen or c stdio FILE buffering has anything to do with this. Neither is it technically a fault of Asterisk, which is correctly writing data to the socket/stream before closing it. It should be noted that this is also not a fault of the virtual environment, as two different implementations (Virtual Box & KVM/Qemu) both exhibited the same exact results. The failure is too specifically the last write issued to the socket prior to close, and would appear to be a race condition triggered by minor differences resulting from running within a virtual machine.
The shutdown() call is the key to working around this problem. It triggers the socket buffering and/or TCP implementation to close things out and transmit the last of the data reliably prior to closing the socket for real. The fflush() issued just prior to that is only to insure that the FILE buffering is flushed out to the file descriptor prior to the shutdown call. The shutdown() call does not actually close the socket, only informs TCP that there will be nothing more sent, which resolves this issue.
</pre>
<br />
<p>- Scott</p>
<br />
<p>On March 26th, 2014, 3:13 p.m. CDT, Scott Griepentrog 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.</div>
<div>By Scott Griepentrog.</div>
<p style="color: grey;"><i>Updated March 26, 2014, 3:13 p.m.</i></p>
<div style="margin-top: 1.5em;">
<b style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Bugs: </b>
<a href="https://issues.asterisk.org/jira/browse/SWP-6767">SWP-6767</a>
</div>
<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;">When running asterisk in a virtual machine, responses to ARI requests would frequently be missing. A race condition related to closing the socket immediately after writing data onto it is resolved in this patch by insuring the output stream is flushed, and then informing TCP of the shutdown prior to the close.</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;">Tested on Ubuntu server 12.04 with Sam's json api test from issue.</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>/branches/12/main/http.c <span style="color: grey">(411242)</span></li>
</ul>
<p><a href="https://reviewboard.asterisk.org/r/3402/diff/" style="margin-left: 3em;">View Diff</a></p>
</td>
</tr>
</table>
</div>
</body>
</html>