summaryrefslogtreecommitdiff
path: root/lib/poll.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/poll.c')
-rw-r--r--lib/poll.c83
1 files changed, 33 insertions, 50 deletions
diff --git a/lib/poll.c b/lib/poll.c
index 7b1e58266..bf8dd1c97 100644
--- a/lib/poll.c
+++ b/lib/poll.c
@@ -1,7 +1,7 @@
/* Emulation for poll(2)
Contributed by Paolo Bonzini.
- Copyright 2001-2003, 2006-2014 Free Software Foundation, Inc.
+ Copyright 2001-2003, 2006-2016 Free Software Foundation, Inc.
This file is part of gnulib.
@@ -33,7 +33,6 @@
#include <errno.h>
#include <limits.h>
-#include <assert.h>
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# define WINDOWS_NATIVE
@@ -45,11 +44,12 @@
# include "msvc-nothrow.h"
#else
# include <sys/time.h>
-# include <sys/socket.h>
-# include <sys/select.h>
# include <unistd.h>
#endif
+#include <sys/select.h>
+#include <sys/socket.h>
+
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
@@ -59,6 +59,8 @@
#include <time.h>
+#include "assure.h"
+
#ifndef INFTIM
# define INFTIM (-1)
#endif
@@ -70,9 +72,11 @@
#ifdef WINDOWS_NATIVE
-/* Optimized test whether a HANDLE refers to a console.
- See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
-#define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
+static BOOL IsConsoleHandle (HANDLE h)
+{
+ DWORD mode;
+ return GetConsoleMode (h, &mode) != 0;
+}
static BOOL
IsSocketHandle (HANDLE h)
@@ -331,26 +335,15 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
int maxfd, rc;
nfds_t i;
-# ifdef _SC_OPEN_MAX
- static int sc_open_max = -1;
-
- if (nfd < 0
- || (nfd > sc_open_max
- && (sc_open_max != -1
- || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
+ if (nfd < 0)
{
errno = EINVAL;
return -1;
}
-# else /* !_SC_OPEN_MAX */
-# ifdef OPEN_MAX
- if (nfd < 0 || nfd > OPEN_MAX)
- {
- errno = EINVAL;
- return -1;
- }
-# endif /* OPEN_MAX -- else, no check is needed */
-# endif /* !_SC_OPEN_MAX */
+ /* Don't check directly for NFD too large. Any practical use of a
+ too-large NFD is caught by one of the other checks below, and
+ checking directly for getdtablesize is too much of a portability
+ and/or performance and/or correctness hassle. */
/* EFAULT is not necessary to implement, but let's do it in the
simplest case. */
@@ -391,10 +384,17 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
{
if (pfd[i].fd < 0)
continue;
-
+ if (maxfd < pfd[i].fd)
+ {
+ maxfd = pfd[i].fd;
+ if (FD_SETSIZE <= maxfd)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ }
if (pfd[i].events & (POLLIN | POLLRDNORM))
FD_SET (pfd[i].fd, &rfds);
-
/* see select(2): "the only exceptional condition detectable
is out-of-band data received on a socket", hence we push
POLLWRBAND events onto wfds instead of efds. */
@@ -402,18 +402,6 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
FD_SET (pfd[i].fd, &wfds);
if (pfd[i].events & (POLLPRI | POLLRDBAND))
FD_SET (pfd[i].fd, &efds);
- if (pfd[i].fd >= maxfd
- && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
- | POLLRDNORM | POLLRDBAND
- | POLLWRNORM | POLLWRBAND)))
- {
- maxfd = pfd[i].fd;
- if (maxfd > FD_SETSIZE)
- {
- errno = EOVERFLOW;
- return -1;
- }
- }
}
/* examine fd sets */
@@ -424,18 +412,13 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
/* establish results */
rc = 0;
for (i = 0; i < nfd; i++)
- if (pfd[i].fd < 0)
- pfd[i].revents = 0;
- else
- {
- int happened = compute_revents (pfd[i].fd, pfd[i].events,
- &rfds, &wfds, &efds);
- if (happened)
- {
- pfd[i].revents = happened;
- rc++;
- }
- }
+ {
+ pfd[i].revents = (pfd[i].fd < 0
+ ? 0
+ : compute_revents (pfd[i].fd, pfd[i].events,
+ &rfds, &wfds, &efds));
+ rc += pfd[i].revents != 0;
+ }
return rc;
#else
@@ -478,7 +461,7 @@ restart:
continue;
h = (HANDLE) _get_osfhandle (pfd[i].fd);
- assert (h != NULL);
+ assure (h != NULL);
if (IsSocketHandle (h))
{
int requested = FD_CLOSE;