/* 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.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ with this program; if not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <alloca.h>
#include <conio.h>
#include <time.h>
+/* Get the overridden 'struct timeval'. */
+#include <sys/time.h>
+
#include "msvc-nothrow.h"
+#undef select
+
struct bitset {
unsigned char in[FD_SETSIZE / CHAR_BIT];
unsigned char out[FD_SETSIZE / CHAR_BIT];
/* 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) (((long) (h) & 3) == 3)
+#define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
static BOOL
IsSocketHandle (HANDLE h)
int
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
struct timeval *timeout)
+#undef timeval
{
static struct timeval tv0;
static HANDLE hEvent;
}
}
+ /* 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)
{