diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-09-11 19:31:52 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-09-11 19:31:52 +0000 |
commit | a9fda6c0afe5659aa78c92f3b12d3d2bd38bba65 (patch) | |
tree | 73408179fdc50341857372673bcb5a51041235d8 | |
parent | 163c619378cab13dce25ab7c933aee34749353ab (diff) | |
download | px4-nuttx-a9fda6c0afe5659aa78c92f3b12d3d2bd38bba65.tar.gz px4-nuttx-a9fda6c0afe5659aa78c92f3b12d3d2bd38bba65.tar.bz2 px4-nuttx-a9fda6c0afe5659aa78c92f3b12d3d2bd38bba65.zip |
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
-rw-r--r-- | nuttx/ChangeLog | 3 | ||||
-rw-r--r-- | nuttx/Documentation/NuttX.html | 5 | ||||
-rw-r--r-- | nuttx/net/net_close.c | 35 | ||||
-rw-r--r-- | nuttx/net/uip/uip_tcpinput.c | 1 |
4 files changed, 28 insertions, 16 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index b26a42e3a..93150d588 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -860,3 +860,6 @@ 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 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! diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index 37caa7933..9c7269825 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -8,7 +8,7 @@ <tr align="center" bgcolor="#e4e4e4"> <td> <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> </tr> </table> @@ -1521,6 +1521,9 @@ nuttx-0.4.11 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 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 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 <spudmonkey@racsa.co.cr> diff --git a/nuttx/net/net_close.c b/nuttx/net/net_close.c index eb7dbd711..b05fc338f 100644 --- a/nuttx/net/net_close.c +++ b/nuttx/net/net_close.c @@ -158,30 +158,35 @@ static inline void netclose_disconnect(FAR struct socket *psock) { 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 (state.cl_cb) + if (conn->tcpstateflags == UIP_ESTABLISHED) { - state.cl_psock = psock; - sem_init(&state.cl_sem, 0, 0); + /* Set up to receive TCP data event callbacks */ - state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT; - state.cl_cb->priv = (void*)&state; - state.cl_cb->event = netclose_interrupt; + state.cl_cb = uip_tcpcallbackalloc(conn); + if (state.cl_cb) + { + 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); - uip_tcpcallbackfree(conn, state.cl_cb); + /* We are now disconnected */ + + sem_destroy(&state.cl_sem); + uip_tcpcallbackfree(conn, state.cl_cb); + } } } diff --git a/nuttx/net/uip/uip_tcpinput.c b/nuttx/net/uip/uip_tcpinput.c index 3fc491f6b..f417c2c7b 100644 --- a/nuttx/net/uip/uip_tcpinput.c +++ b/nuttx/net/uip/uip_tcpinput.c @@ -166,6 +166,7 @@ void uip_tcpinput(struct uip_driver_s *dev) * least queue it it for acceptance). */ + conn->tcpstateflags = UIP_ESTABLISHED; if (uip_accept(dev, conn, tmp16) != OK) { /* No, then we have to give the connection back */ |