Fix a whole in the logic from the previous check-in

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5718 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-03-07 18:43:03 +00:00
parent 4b3ad32ee5
commit 8a774a1712
3 changed files with 52 additions and 5 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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);
}