/* Emulation for select(2)
Contributed by Paolo Bonzini.
- Copyright 2008-2012 Free Software Foundation, Inc.
+ Copyright 2008-2013 Free Software Foundation, Inc.
This file is part of gnulib.
}
}
+ /* Place a sentinel at the end of the array. */
+ handle_array[nhandles] = NULL;
+
+restart:
if (wait_timeout == 0 || nsock == 0)
rc = 0;
else
if (rc == 0 && nsock > 0)
rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
+ if (nhandles > 1)
+ {
+ /* Count results that are not counted in the return value of select. */
+ nhandles = 1;
+ for (i = 0; i < nfds; i++)
+ {
+ if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
+ continue;
+
+ h = (HANDLE) _get_osfhandle (i);
+ if (h == handle_array[nhandles])
+ {
+ /* Not a socket. */
+ nhandles++;
+ windows_poll_handle (h, i, &rbits, &wbits, &xbits);
+ if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
+ || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
+ || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
+ rc++;
+ }
+ }
+
+ if (rc == 0 && wait_timeout == INFINITE)
+ {
+ /* Sleep 1 millisecond to avoid busy wait and retry with the
+ original fd_sets. */
+ memcpy (&handle_rfds, rfds, sizeof (fd_set));
+ memcpy (&handle_wfds, wfds, sizeof (fd_set));
+ memcpy (&handle_xfds, xfds, sizeof (fd_set));
+ SleepEx (1, TRUE);
+ goto restart;
+ }
+ }
+
/* Now fill in the results. */
FD_ZERO (rfds);
FD_ZERO (wfds);
FD_ZERO (xfds);
-
- /* Place a sentinel at the end of the array. */
- handle_array[nhandles] = NULL;
nhandles = 1;
for (i = 0; i < nfds; i++)
{
h = (HANDLE) _get_osfhandle (i);
if (h != handle_array[nhandles])
{
- /* Perform handle->descriptor mapping. Don't update rc, as these
- results are counted in the return value of Winsock's select. */
+ /* Perform handle->descriptor mapping. */
WSAEventSelect ((SOCKET) h, NULL, 0);
if (FD_ISSET (h, &handle_rfds))
FD_SET (i, rfds);
{
/* Not a socket. */
nhandles++;
- windows_poll_handle (h, i, &rbits, &wbits, &xbits);
if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
- {
- rc++;
- FD_SET (i, rfds);
- }
+ FD_SET (i, rfds);
if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
- {
- rc++;
- FD_SET (i, wfds);
- }
+ FD_SET (i, wfds);
if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
- {
- rc++;
- FD_SET (i, xfds);
- }
+ FD_SET (i, xfds);
}
}
#else /* ! Native Windows. */
#include <sys/select.h>
+#include <stddef.h> /* NULL */
+#include <errno.h>
+#include <unistd.h>
#undef select
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
struct timeval *timeout)
{
+ int i;
+
+ /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
+ if (nfds < 0 || nfds > FD_SETSIZE)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ for (i = 0; i < nfds; i++)
+ {
+ if (((rfds && FD_ISSET (i, rfds))
+ || (wfds && FD_ISSET (i, wfds))
+ || (xfds && FD_ISSET (i, xfds)))
+ && dup2 (i, i) != i)
+ return -1;
+ }
+
/* Interix 3.5 has a bug: it does not support nfds == 0. */
if (nfds == 0)
{