diff --git a/ChangeLog b/ChangeLog index b26a42e3aa8accfbde009b510618de80768a68c2..93150d588a4f0923c8e3fd36e2fe7a5c2880f087 100644 --- a/ChangeLog +++ b/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/Documentation/NuttX.html b/Documentation/NuttX.html index 37caa793370e3ac4185b6f69ed061977bb89dc8c..9c7269825ff20d2b3ff527aa82a8464c8ac8fb81 100644 --- a/Documentation/NuttX.html +++ b/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/net/net_close.c b/net/net_close.c index eb7dbd7114b6ff1c78b263d12bb74e9da59715b7..b05fc338f4529682c043d8e15851b81b83b94c15 100644 --- a/net/net_close.c +++ b/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/net/uip/uip_tcpinput.c b/net/uip/uip_tcpinput.c index 3fc491f6b4fae1829927975803ba57374defcfe9..f417c2c7b0834c59acbc1577325aadb907be57c6 100644 --- a/net/uip/uip_tcpinput.c +++ b/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 */