diff options
-rw-r--r-- | nuttx/ChangeLog | 19 | ||||
-rw-r--r-- | nuttx/include/nuttx/net/net.h | 2 | ||||
-rw-r--r-- | nuttx/net/net_poll.c | 36 |
3 files changed, 52 insertions, 5 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 6e9434e19..753e4c88c 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4262,3 +4262,22 @@ * arch/arm: Correct some bad syscall dispatching logic. This change cannot be fully tested until there is a fielded NuttX kernel build. (2013-03-06). + * net/net_poll.c: Correct logic that checks if the socket is + disconnected when the poll is setup. That is bad logic: Listen + sockets, for example, are not connected. In that case, the purpose of + the poll is to wait for connection events. As a result of this, + poll/select would return immediately with POLLHUP with it was used to + detect connection events. This fix for now was to check instead if + the socket is closed (meaning that it was connected at one time but + was closed by the remote peer). That excludes the listen socket which + was never connected. This does introduce a new problem, however. If + the socket was not closed, but lost the connection through an abnormal + event, then poll/select will hang. That needs to be revisited.\ + (2013-03-07) + * fs/fs_selected.c: Was not checking if the timeout parameter was NULL + but would, instead, setup a bogus timeout based on whatever it found at + address zero. Also, improved some of the memory allocation logic so + that it will not use so much memory. (2013-03-07) + * net/net_poll.c: Handle the missing case. Now tests for not connected + AND not listening. I think that now covers all of the cases including + the missing case noted above. (2013-03-07) diff --git a/nuttx/include/nuttx/net/net.h b/nuttx/include/nuttx/net/net.h index d23fb8796..a7f8f0578 100644 --- a/nuttx/include/nuttx/net/net.h +++ b/nuttx/include/nuttx/net/net.h @@ -97,7 +97,7 @@ struct socket socktimeo_t s_sndtimeo; /* Send timeout value (in deciseconds) */ #endif #endif - void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */ + FAR void *s_conn; /* Connection: struct uip_conn or uip_udp_conn */ }; /* This defines a list of sockets indexed by the socket descriptor */ diff --git a/nuttx/net/net_poll.c b/nuttx/net/net_poll.c index 583d469a7..55ede320d 100644 --- a/nuttx/net/net_poll.c +++ b/nuttx/net/net_poll.c @@ -258,20 +258,48 @@ static inline int net_pollsetup(FAR struct socket *psock, * * 1) The socket is connected and we are waiting for data availability * events. + * + * __SS_ISCONNECTED(f) == true + * __SS_ISLISTENING(f) == false + * __SS_ISCLOSED(f) == false + * + * Action: Wait for data availability events + * * 2) This is a listener socket that was never connected and we are * waiting for connection events. + * + * __SS_ISCONNECTED(f) == false + * __SS_ISLISTENING(f) == true + * __SS_ISCLOSED(f) == false + * + * Action: Wait for connection events + * * 3) This socket was previously connected, but the peer has gracefully * closed the connection. + * + * __SS_ISCONNECTED(f) == false + * __SS_ISLISTENING(f) == false + * __SS_ISCLOSED(f) == true + * + * Action: Return with POLLHUP|POLLERR events + * * 4) This socket was previously connected, but we lost the connection * due to some exceptional event. * - * We can detect 1) and 3), but 2) and 4) appear the same. So we - * do the best we can for now: We will report POLLHUP if the socket - * has been gracefully closed. + * __SS_ISCONNECTED(f) == false + * __SS_ISLISTENING(f) == false + * __SS_ISCLOSED(f) == false + * + * Action: Return with POLLHUP|POLLERR events */ - if (_SS_ISCLOSED(psock->s_flags)) + if (!_SS_ISCONNECTED(psock->s_flags) && !_SS_ISLISTENING(psock->s_flags)) { + /* We were previously connected but lost the connection either due + * to a graceful shutdown by the remote peer or because of some + * exceptional event. + */ + fds->revents |= (POLLERR | POLLHUP); } |