From 27ba470482b94358b2d5ec525c91e335d85171f1 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 10 Sep 2009 22:55:52 +0000 Subject: [PATCH] Fix race condition bug in poll() for backlogged connections git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2032 42af7a65-404d-4744-a932-0658087f49c3 --- ChangeLog | 4 ++++ Documentation/NuttX.html | 6 +++++- include/net/uip/uip-tcp.h | 6 ++++++ net/net_poll.c | 6 ++++++ net/uip/uip_tcpbacklog.c | 19 +++++++++++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6c138a9f1b..b26a42e3aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -856,3 +856,7 @@ extra two bytes of length cause the driver to sometimes read one too many words from the received FIFO (corrupting the next queued receive packet, if any). + * net/net_poll.c and net/uip/uip_tcpbacklog.c. Fixed an important race condition + 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. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 2223e362c8..37caa79337 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: September 09, 2009

+

Last Updated: September 10, 2009

@@ -1517,6 +1517,10 @@ nuttx-0.4.11 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> extra two bytes of length cause the driver to sometimes read one too many words from the received FIFO (corrupting the next queued receive packet, if any). + * net/net_poll.c and net/uip/uip_tcpbacklog.c. Fixed an important race condition + 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. pascal-0.1.3 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/include/net/uip/uip-tcp.h b/include/net/uip/uip-tcp.h index 1fe199e700..4b61c8f2a8 100644 --- a/include/net/uip/uip-tcp.h +++ b/include/net/uip/uip-tcp.h @@ -400,6 +400,11 @@ extern int uip_backlogdestroy(FAR struct uip_conn *conn); /* APIs to manage individual backlog actions */ extern int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn); +#ifndef CONFIG_DISABLE_POLL +extern boolean uip_backlogavailable(FAR struct uip_conn *conn); +#else +# define uip_backlogavailable(conn) (FALSE); +#endif extern FAR struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn); extern int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn); @@ -407,6 +412,7 @@ extern int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blc # define uip_backlogcreate(conn,nblg) (-ENOSYS) # define uip_backlogdestroy(conn) (-ENOSYS) # define uip_backlogadd(conn,blconn) (-ENOSYS) +# define uip_backlogavailable(conn) (FALSE); # define uip_backlogremove(conn) (NULL) #endif diff --git a/net/net_poll.c b/net/net_poll.c index fac6186c4a..0c5e5c75d4 100644 --- a/net/net_poll.c +++ b/net/net_poll.c @@ -201,9 +201,15 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds) fds->priv = (FAR void *)cb; +#ifdef CONFIG_NET_TCPBACKLOG + /* Check for read data or backlogged connection availability now */ + + if (!sq_empty(&conn->readahead) || uip_backlogavailable(conn)) +#else /* Check for read data availability now */ if (!sq_empty(&conn->readahead)) +#endif { fds->revents = fds->events & POLLIN; if (fds->revents != 0) diff --git a/net/uip/uip_tcpbacklog.c b/net/uip/uip_tcpbacklog.c index 8e6d1fb904..d97acde9c6 100644 --- a/net/uip/uip_tcpbacklog.c +++ b/net/uip/uip_tcpbacklog.c @@ -261,6 +261,25 @@ int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn) return ret; } +/**************************************************************************** + * Function: uip_backlogremove + * + * Description: + * Called from poll(). Before waiting for a new connection, poll will + * call this API to see if there are pending connections in the backlog. + * + * Assumptions: + * Called from normal user code, but with interrupts disabled, + * + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_POLL +boolean uip_backlogavailable(FAR struct uip_conn *conn) +{ + return (conn && conn->backlog && !sq_empty(&conn->backlog->bl_pending)); +} +#endif + /**************************************************************************** * Function: uip_backlogremove *