Fix race condition that can cause close of socket to hang

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2037 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-09-11 19:31:52 +00:00
parent c8dec461fc
commit 80113f7d41
4 changed files with 28 additions and 16 deletions

View File

@ -860,3 +860,6 @@
bug in polling for connections. The logic worked if the poll was inplace bug in polling for connections. The logic worked if the poll was inplace
before the connection was received; but the poll failed to awaken if the before the connection was received; but the poll failed to awaken if the
connection was already pending in the backlog when poll() was called. connection was already pending in the backlog when poll() was called.
* net/net_close.c. Fixed another important TCP/IP race condition bug: If
the host closes the TCP connection just before the target calls close(), then
the close operation may hang indefinitely!

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4"> <tr align="center" bgcolor="#e4e4e4">
<td> <td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1> <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: September 10, 2009</p> <p>Last Updated: September 11, 2009</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -1521,6 +1521,9 @@ nuttx-0.4.11 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
bug in polling for connections. The logic worked if the poll was inplace bug in polling for connections. The logic worked if the poll was inplace
before the connection was received; but the poll failed to awaken if the before the connection was received; but the poll failed to awaken if the
connection was already pending in the backlog when poll() was called. connection was already pending in the backlog when poll() was called.
* net/net_close.c. Fixed another important TCP/IP race condition bug: If
the host closes the TCP connection just before the target calls close(), then
the close operation may hang indefinitely!
pascal-0.1.3 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt; pascal-0.1.3 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;

View File

@ -158,30 +158,35 @@ static inline void netclose_disconnect(FAR struct socket *psock)
{ {
struct uip_conn *conn = (struct uip_conn*)psock->s_conn; struct uip_conn *conn = (struct uip_conn*)psock->s_conn;
/* Set up to receive TCP data event callbacks */ /* Check for the case where the host beat us and disconnected first */
state.cl_cb = uip_tcpcallbackalloc(conn); if (conn->tcpstateflags == UIP_ESTABLISHED)
if (state.cl_cb)
{ {
state.cl_psock = psock; /* Set up to receive TCP data event callbacks */
sem_init(&state.cl_sem, 0, 0);
state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT; state.cl_cb = uip_tcpcallbackalloc(conn);
state.cl_cb->priv = (void*)&state; if (state.cl_cb)
state.cl_cb->event = netclose_interrupt; {
state.cl_psock = psock;
sem_init(&state.cl_sem, 0, 0);
/* Notify the device driver of the availaibilty of TX data */ state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT;
state.cl_cb->priv = (void*)&state;
state.cl_cb->event = netclose_interrupt;
netdev_txnotify(&conn->ripaddr); /* Notify the device driver of the availaibilty of TX data */
/* Wait for the disconnect event */ netdev_txnotify(&conn->ripaddr);
(void)sem_wait(&state.cl_sem); /* Wait for the disconnect event */
/* We are now disconnected */ (void)sem_wait(&state.cl_sem);
sem_destroy(&state.cl_sem); /* We are now disconnected */
uip_tcpcallbackfree(conn, state.cl_cb);
sem_destroy(&state.cl_sem);
uip_tcpcallbackfree(conn, state.cl_cb);
}
} }
} }

View File

@ -166,6 +166,7 @@ void uip_tcpinput(struct uip_driver_s *dev)
* least queue it it for acceptance). * least queue it it for acceptance).
*/ */
conn->tcpstateflags = UIP_ESTABLISHED;
if (uip_accept(dev, conn, tmp16) != OK) if (uip_accept(dev, conn, tmp16) != OK)
{ {
/* No, then we have to give the connection back */ /* No, then we have to give the connection back */