From a9fda6c0afe5659aa78c92f3b12d3d2bd38bba65 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 11 Sep 2009 19:31:52 +0000 Subject: 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 --- nuttx/net/net_close.c | 35 ++++++++++++++++++++--------------- nuttx/net/uip/uip_tcpinput.c | 1 + 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'nuttx/net') 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 */ -- cgit v1.2.3