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, 50 insertions, 33 deletions
diff --git a/lib/poll.c b/lib/poll.c
index e70e8b354..7b1e58266 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-2015 Free Software Foundation, Inc.
+ Copyright 2001-2003, 2006-2014 Free Software Foundation, Inc.
This file is part of gnulib.
@@ -33,6 +33,7 @@
#include <errno.h>
#include <limits.h>
+#include <assert.h>
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# define WINDOWS_NATIVE
@@ -44,12 +45,11 @@
# 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,8 +59,6 @@
#include <time.h>
-#include "assure.h"
-
#ifndef INFTIM
# define INFTIM (-1)
#endif
@@ -72,11 +70,9 @@
#ifdef WINDOWS_NATIVE
-static BOOL IsConsoleHandle (HANDLE h)
-{
- DWORD mode;
- return GetConsoleMode (h, &mode) != 0;
-}
+/* 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
IsSocketHandle (HANDLE h)
@@ -335,15 +331,26 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
int maxfd, rc;
nfds_t i;
- if (nfd < 0)
+# 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)))))
{
errno = EINVAL;
return -1;
}
- /* 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. */
+# 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 */
/* EFAULT is not necessary to implement, but let's do it in the
simplest case. */
@@ -384,17 +391,10 @@ 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,6 +402,18 @@ 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 */
@@ -412,13 +424,18 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
/* establish results */
rc = 0;
for (i = 0; i < nfd; i++)
- {
- pfd[i].revents = (pfd[i].fd < 0
- ? 0
- : compute_revents (pfd[i].fd, pfd[i].events,
- &rfds, &wfds, &efds));
- rc += pfd[i].revents != 0;
- }
+ 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++;
+ }
+ }
return rc;
#else
@@ -461,7 +478,7 @@ restart:
continue;
h = (HANDLE) _get_osfhandle (pfd[i].fd);
- assure (h != NULL);
+ assert (h != NULL);
if (IsSocketHandle (h))
{
int requested = FD_CLOSE;