From 58ef30a4e7b8409a5a225e2a82a93cbbdd19216d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 23 Aug 2011 14:05:04 +0000 Subject: [PATCH] * poll.cc (poll): Don't return prematurely if invalid fds have been encountered. Enforce timeout set to 0 in case of invalid fds. Take number of invalid fds into account when returning. --- winsup/cygwin/ChangeLog | 6 ++++++ winsup/cygwin/poll.cc | 25 ++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index d959184e1..c55014c27 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,9 @@ +2011-08-23 Corinna Vinschen + + * poll.cc (poll): Don't return prematurely if invalid fds have been + encountered. Enforce timeout set to 0 in case of invalid fds. Take + number of invalid fds into account when returning. + 2011-08-23 Corinna Vinschen * fhandler_socket.cc (fhandler_socket::send_internal): Fix setting diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc index 3c342adfd..ea86ab5aa 100644 --- a/winsup/cygwin/poll.cc +++ b/winsup/cygwin/poll.cc @@ -28,6 +28,7 @@ extern "C" int poll (struct pollfd *fds, nfds_t nfds, int timeout) { int max_fd = 0; + int invalid_fds = 0; fd_set *read_fds, *write_fds, *except_fds; struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; @@ -51,7 +52,6 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout) memset (write_fds, 0, fds_size); memset (except_fds, 0, fds_size); - int invalid_fds = 0; for (unsigned int i = 0; i < nfds; ++i) { fds[i].revents = 0; @@ -71,20 +71,31 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout) } } - if (invalid_fds) - return invalid_fds; + /* Invalid fds? */ + if (invalid_fds > 0) + { + /* Only invalid fds? Return. */ + if ((nfds_t) invalid_fds == nfds) + return invalid_fds; + /* POSIX doesn't explicitely define this behaviour, but on Linux, + the timeout is set to 0 if an error occurs, and POLLNVAL is one + of these errors. So, for Linux-compatibility's sake... */ + tv.tv_sec = tv.tv_usec = 0; + } int ret = cygwin_select (max_fd + 1, read_fds, write_fds, except_fds, timeout < 0 ? NULL : &tv); + /* timeout, signal, whatever? Return. If invalid fds exist, return with + their number. */ if (ret <= 0) - return ret; + return invalid_fds ?: ret; /* Set revents fields and count fds with non-zero revents fields for return value. */ ret = 0; for (unsigned int i = 0; i < nfds; ++i) { - if (fds[i].fd >= 0) + if (fds[i].fd >= 0 && fds[i].revents != POLLNVAL) { fhandler_socket *sock; @@ -123,8 +134,8 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout) ++ret; } } - - return ret; + /* Number of fds with event includes the invalid fds. */ + return ret + invalid_fds; } extern "C" int