Home | History | Annotate | Line # | Download | only in import
      1  1.1  christos /* Emulation for select(2)
      2  1.1  christos    Contributed by Paolo Bonzini.
      3  1.1  christos 
      4  1.1  christos    Copyright 2008-2022 Free Software Foundation, Inc.
      5  1.1  christos 
      6  1.1  christos    This file is part of gnulib.
      7  1.1  christos 
      8  1.1  christos    This file is free software: you can redistribute it and/or modify
      9  1.1  christos    it under the terms of the GNU Lesser General Public License as
     10  1.1  christos    published by the Free Software Foundation; either version 2.1 of the
     11  1.1  christos    License, or (at your option) any later version.
     12  1.1  christos 
     13  1.1  christos    This file is distributed in the hope that it will be useful,
     14  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  christos    GNU Lesser General Public License for more details.
     17  1.1  christos 
     18  1.1  christos    You should have received a copy of the GNU Lesser General Public License
     19  1.1  christos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
     20  1.1  christos 
     21  1.1  christos #include <config.h>
     22  1.1  christos 
     23  1.1  christos /* Specification.  */
     24  1.1  christos #include <sys/select.h>
     25  1.1  christos 
     26  1.1  christos #if defined _WIN32 && ! defined __CYGWIN__
     27  1.1  christos /* Native Windows.  */
     28  1.1  christos 
     29  1.1  christos #include <alloca.h>
     30  1.1  christos #include <assert.h>
     31  1.1  christos #include <sys/types.h>
     32  1.1  christos #include <errno.h>
     33  1.1  christos #include <limits.h>
     34  1.1  christos 
     35  1.1  christos #include <winsock2.h>
     36  1.1  christos #include <windows.h>
     37  1.1  christos #include <io.h>
     38  1.1  christos #include <stdio.h>
     39  1.1  christos #include <conio.h>
     40  1.1  christos #include <time.h>
     41  1.1  christos 
     42  1.1  christos /* Get the overridden 'struct timeval'.  */
     43  1.1  christos #include <sys/time.h>
     44  1.1  christos 
     45  1.1  christos #if GNULIB_MSVC_NOTHROW
     46  1.1  christos # include "msvc-nothrow.h"
     47  1.1  christos #else
     48  1.1  christos # include <io.h>
     49  1.1  christos #endif
     50  1.1  christos 
     51  1.1  christos #undef select
     52  1.1  christos 
     53  1.1  christos /* Don't assume that UNICODE is not defined.  */
     54  1.1  christos #undef GetModuleHandle
     55  1.1  christos #define GetModuleHandle GetModuleHandleA
     56  1.1  christos #undef PeekConsoleInput
     57  1.1  christos #define PeekConsoleInput PeekConsoleInputA
     58  1.1  christos #undef CreateEvent
     59  1.1  christos #define CreateEvent CreateEventA
     60  1.1  christos #undef PeekMessage
     61  1.1  christos #define PeekMessage PeekMessageA
     62  1.1  christos #undef DispatchMessage
     63  1.1  christos #define DispatchMessage DispatchMessageA
     64  1.1  christos 
     65  1.1  christos /* Avoid warnings from gcc -Wcast-function-type.  */
     66  1.1  christos #define GetProcAddress \
     67  1.1  christos   (void *) GetProcAddress
     68  1.1  christos 
     69  1.1  christos struct bitset {
     70  1.1  christos   unsigned char in[FD_SETSIZE / CHAR_BIT];
     71  1.1  christos   unsigned char out[FD_SETSIZE / CHAR_BIT];
     72  1.1  christos };
     73  1.1  christos 
     74  1.1  christos /* Declare data structures for ntdll functions.  */
     75  1.1  christos typedef struct _FILE_PIPE_LOCAL_INFORMATION {
     76  1.1  christos   ULONG NamedPipeType;
     77  1.1  christos   ULONG NamedPipeConfiguration;
     78  1.1  christos   ULONG MaximumInstances;
     79  1.1  christos   ULONG CurrentInstances;
     80  1.1  christos   ULONG InboundQuota;
     81  1.1  christos   ULONG ReadDataAvailable;
     82  1.1  christos   ULONG OutboundQuota;
     83  1.1  christos   ULONG WriteQuotaAvailable;
     84  1.1  christos   ULONG NamedPipeState;
     85  1.1  christos   ULONG NamedPipeEnd;
     86  1.1  christos } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
     87  1.1  christos 
     88  1.1  christos typedef struct _IO_STATUS_BLOCK
     89  1.1  christos {
     90  1.1  christos   union {
     91  1.1  christos     DWORD Status;
     92  1.1  christos     PVOID Pointer;
     93  1.1  christos   } u;
     94  1.1  christos   ULONG_PTR Information;
     95  1.1  christos } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
     96  1.1  christos 
     97  1.1  christos typedef enum _FILE_INFORMATION_CLASS {
     98  1.1  christos   FilePipeLocalInformation = 24
     99  1.1  christos } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
    100  1.1  christos 
    101  1.1  christos typedef DWORD (WINAPI *PNtQueryInformationFile)
    102  1.1  christos          (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
    103  1.1  christos 
    104  1.1  christos #ifndef PIPE_BUF
    105  1.1  christos #define PIPE_BUF        512
    106  1.1  christos #endif
    107  1.1  christos 
    108  1.1  christos static BOOL IsConsoleHandle (HANDLE h)
    109  1.1  christos {
    110  1.1  christos   DWORD mode;
    111  1.1  christos   return GetConsoleMode (h, &mode) != 0;
    112  1.1  christos }
    113  1.1  christos 
    114  1.1  christos static BOOL
    115  1.1  christos IsSocketHandle (HANDLE h)
    116  1.1  christos {
    117  1.1  christos   WSANETWORKEVENTS ev;
    118  1.1  christos 
    119  1.1  christos   if (IsConsoleHandle (h))
    120  1.1  christos     return FALSE;
    121  1.1  christos 
    122  1.1  christos   /* Under Wine, it seems that getsockopt returns 0 for pipes too.
    123  1.1  christos      WSAEnumNetworkEvents instead distinguishes the two correctly.  */
    124  1.1  christos   ev.lNetworkEvents = 0xDEADBEEF;
    125  1.1  christos   WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
    126  1.1  christos   return ev.lNetworkEvents != 0xDEADBEEF;
    127  1.1  christos }
    128  1.1  christos 
    129  1.1  christos /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
    130  1.1  christos    H).  */
    131  1.1  christos 
    132  1.1  christos static int
    133  1.1  christos windows_poll_handle (HANDLE h, int fd,
    134  1.1  christos                      struct bitset *rbits,
    135  1.1  christos                      struct bitset *wbits,
    136  1.1  christos                      struct bitset *xbits)
    137  1.1  christos {
    138  1.1  christos   BOOL read, write, except;
    139  1.1  christos   int i, ret;
    140  1.1  christos   INPUT_RECORD *irbuffer;
    141  1.1  christos   DWORD avail, nbuffer;
    142  1.1  christos   BOOL bRet;
    143  1.1  christos   IO_STATUS_BLOCK iosb;
    144  1.1  christos   FILE_PIPE_LOCAL_INFORMATION fpli;
    145  1.1  christos   static PNtQueryInformationFile NtQueryInformationFile;
    146  1.1  christos   static BOOL once_only;
    147  1.1  christos 
    148  1.1  christos   read = write = except = FALSE;
    149  1.1  christos   switch (GetFileType (h))
    150  1.1  christos     {
    151  1.1  christos     case FILE_TYPE_DISK:
    152  1.1  christos       read = TRUE;
    153  1.1  christos       write = TRUE;
    154  1.1  christos       break;
    155  1.1  christos 
    156  1.1  christos     case FILE_TYPE_PIPE:
    157  1.1  christos       if (!once_only)
    158  1.1  christos         {
    159  1.1  christos           NtQueryInformationFile = (PNtQueryInformationFile)
    160  1.1  christos             GetProcAddress (GetModuleHandle ("ntdll.dll"),
    161  1.1  christos                             "NtQueryInformationFile");
    162  1.1  christos           once_only = TRUE;
    163  1.1  christos         }
    164  1.1  christos 
    165  1.1  christos       if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
    166  1.1  christos         {
    167  1.1  christos           if (avail)
    168  1.1  christos             read = TRUE;
    169  1.1  christos         }
    170  1.1  christos       else if (GetLastError () == ERROR_BROKEN_PIPE)
    171  1.1  christos         ;
    172  1.1  christos 
    173  1.1  christos       else
    174  1.1  christos         {
    175  1.1  christos           /* It was the write-end of the pipe.  Check if it is writable.
    176  1.1  christos              If NtQueryInformationFile fails, optimistically assume the pipe is
    177  1.1  christos              writable.  This could happen on Windows 9x, where
    178  1.1  christos              NtQueryInformationFile is not available, or if we inherit a pipe
    179  1.1  christos              that doesn't permit FILE_READ_ATTRIBUTES access on the write end
    180  1.1  christos              (I think this should not happen since Windows XP SP2; WINE seems
    181  1.1  christos              fine too).  Otherwise, ensure that enough space is available for
    182  1.1  christos              atomic writes.  */
    183  1.1  christos           memset (&iosb, 0, sizeof (iosb));
    184  1.1  christos           memset (&fpli, 0, sizeof (fpli));
    185  1.1  christos 
    186  1.1  christos           if (!NtQueryInformationFile
    187  1.1  christos               || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
    188  1.1  christos                                          FilePipeLocalInformation)
    189  1.1  christos               || fpli.WriteQuotaAvailable >= PIPE_BUF
    190  1.1  christos               || (fpli.OutboundQuota < PIPE_BUF &&
    191  1.1  christos                   fpli.WriteQuotaAvailable == fpli.OutboundQuota))
    192  1.1  christos             write = TRUE;
    193  1.1  christos         }
    194  1.1  christos       break;
    195  1.1  christos 
    196  1.1  christos     case FILE_TYPE_CHAR:
    197  1.1  christos       write = TRUE;
    198  1.1  christos       if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    199  1.1  christos         break;
    200  1.1  christos 
    201  1.1  christos       ret = WaitForSingleObject (h, 0);
    202  1.1  christos       if (ret == WAIT_OBJECT_0)
    203  1.1  christos         {
    204  1.1  christos           if (!IsConsoleHandle (h))
    205  1.1  christos             {
    206  1.1  christos               read = TRUE;
    207  1.1  christos               break;
    208  1.1  christos             }
    209  1.1  christos 
    210  1.1  christos           nbuffer = avail = 0;
    211  1.1  christos           bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
    212  1.1  christos 
    213  1.1  christos           /* Screen buffers handles are filtered earlier.  */
    214  1.1  christos           assert (bRet);
    215  1.1  christos           if (nbuffer == 0)
    216  1.1  christos             {
    217  1.1  christos               except = TRUE;
    218  1.1  christos               break;
    219  1.1  christos             }
    220  1.1  christos 
    221  1.1  christos           irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
    222  1.1  christos           bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
    223  1.1  christos           if (!bRet || avail == 0)
    224  1.1  christos             {
    225  1.1  christos               except = TRUE;
    226  1.1  christos               break;
    227  1.1  christos             }
    228  1.1  christos 
    229  1.1  christos           for (i = 0; i < avail; i++)
    230  1.1  christos             if (irbuffer[i].EventType == KEY_EVENT)
    231  1.1  christos               read = TRUE;
    232  1.1  christos         }
    233  1.1  christos       break;
    234  1.1  christos 
    235  1.1  christos     default:
    236  1.1  christos       ret = WaitForSingleObject (h, 0);
    237  1.1  christos       write = TRUE;
    238  1.1  christos       if (ret == WAIT_OBJECT_0)
    239  1.1  christos         read = TRUE;
    240  1.1  christos 
    241  1.1  christos       break;
    242  1.1  christos     }
    243  1.1  christos 
    244  1.1  christos   ret = 0;
    245  1.1  christos   if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    246  1.1  christos     {
    247  1.1  christos       rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
    248  1.1  christos       ret++;
    249  1.1  christos     }
    250  1.1  christos 
    251  1.1  christos   if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    252  1.1  christos     {
    253  1.1  christos       wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
    254  1.1  christos       ret++;
    255  1.1  christos     }
    256  1.1  christos 
    257  1.1  christos   if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    258  1.1  christos     {
    259  1.1  christos       xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
    260  1.1  christos       ret++;
    261  1.1  christos     }
    262  1.1  christos 
    263  1.1  christos   return ret;
    264  1.1  christos }
    265  1.1  christos 
    266  1.1  christos int
    267  1.1  christos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
    268  1.1  christos             struct timeval *timeout)
    269  1.1  christos #undef timeval
    270  1.1  christos {
    271  1.1  christos   static struct timeval tv0;
    272  1.1  christos   static HANDLE hEvent;
    273  1.1  christos   HANDLE h, handle_array[FD_SETSIZE + 2];
    274  1.1  christos   fd_set handle_rfds, handle_wfds, handle_xfds;
    275  1.1  christos   struct bitset rbits, wbits, xbits;
    276  1.1  christos   unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
    277  1.1  christos   DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
    278  1.1  christos   MSG msg;
    279  1.1  christos   int i, fd, rc;
    280  1.1  christos   clock_t tend;
    281  1.1  christos 
    282  1.1  christos   if (nfds > FD_SETSIZE)
    283  1.1  christos     nfds = FD_SETSIZE;
    284  1.1  christos 
    285  1.1  christos   if (!timeout)
    286  1.1  christos     wait_timeout = INFINITE;
    287  1.1  christos   else
    288  1.1  christos     {
    289  1.1  christos       wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
    290  1.1  christos 
    291  1.1  christos       /* select is also used as a portable usleep.  */
    292  1.1  christos       if (!rfds && !wfds && !xfds)
    293  1.1  christos         {
    294  1.1  christos           Sleep (wait_timeout);
    295  1.1  christos           return 0;
    296  1.1  christos         }
    297  1.1  christos     }
    298  1.1  christos 
    299  1.1  christos   if (!hEvent)
    300  1.1  christos     hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    301  1.1  christos 
    302  1.1  christos   handle_array[0] = hEvent;
    303  1.1  christos   nhandles = 1;
    304  1.1  christos   nsock = 0;
    305  1.1  christos 
    306  1.1  christos   /* Copy descriptors to bitsets.  At the same time, eliminate
    307  1.1  christos      bits in the "wrong" direction for console input buffers
    308  1.1  christos      and screen buffers, because screen buffers are waitable
    309  1.1  christos      and they will block until a character is available.  */
    310  1.1  christos   memset (&rbits, 0, sizeof (rbits));
    311  1.1  christos   memset (&wbits, 0, sizeof (wbits));
    312  1.1  christos   memset (&xbits, 0, sizeof (xbits));
    313  1.1  christos   memset (anyfds_in, 0, sizeof (anyfds_in));
    314  1.1  christos   if (rfds)
    315  1.1  christos     for (i = 0; i < rfds->fd_count; i++)
    316  1.1  christos       {
    317  1.1  christos         fd = rfds->fd_array[i];
    318  1.1  christos         h = (HANDLE) _get_osfhandle (fd);
    319  1.1  christos         if (IsConsoleHandle (h)
    320  1.1  christos             && !GetNumberOfConsoleInputEvents (h, &nbuffer))
    321  1.1  christos           continue;
    322  1.1  christos 
    323  1.1  christos         rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    324  1.1  christos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    325  1.1  christos       }
    326  1.1  christos   else
    327  1.1  christos     rfds = (fd_set *) alloca (sizeof (fd_set));
    328  1.1  christos 
    329  1.1  christos   if (wfds)
    330  1.1  christos     for (i = 0; i < wfds->fd_count; i++)
    331  1.1  christos       {
    332  1.1  christos         fd = wfds->fd_array[i];
    333  1.1  christos         h = (HANDLE) _get_osfhandle (fd);
    334  1.1  christos         if (IsConsoleHandle (h)
    335  1.1  christos             && GetNumberOfConsoleInputEvents (h, &nbuffer))
    336  1.1  christos           continue;
    337  1.1  christos 
    338  1.1  christos         wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    339  1.1  christos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    340  1.1  christos       }
    341  1.1  christos   else
    342  1.1  christos     wfds = (fd_set *) alloca (sizeof (fd_set));
    343  1.1  christos 
    344  1.1  christos   if (xfds)
    345  1.1  christos     for (i = 0; i < xfds->fd_count; i++)
    346  1.1  christos       {
    347  1.1  christos         fd = xfds->fd_array[i];
    348  1.1  christos         xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    349  1.1  christos         anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
    350  1.1  christos       }
    351  1.1  christos   else
    352  1.1  christos     xfds = (fd_set *) alloca (sizeof (fd_set));
    353  1.1  christos 
    354  1.1  christos   /* Zero all the fd_sets, including the application's.  */
    355  1.1  christos   FD_ZERO (rfds);
    356  1.1  christos   FD_ZERO (wfds);
    357  1.1  christos   FD_ZERO (xfds);
    358  1.1  christos   FD_ZERO (&handle_rfds);
    359  1.1  christos   FD_ZERO (&handle_wfds);
    360  1.1  christos   FD_ZERO (&handle_xfds);
    361  1.1  christos 
    362  1.1  christos   /* Classify handles.  Create fd sets for sockets, poll the others. */
    363  1.1  christos   for (i = 0; i < nfds; i++)
    364  1.1  christos     {
    365  1.1  christos       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
    366  1.1  christos         continue;
    367  1.1  christos 
    368  1.1  christos       h = (HANDLE) _get_osfhandle (i);
    369  1.1  christos       if (!h)
    370  1.1  christos         {
    371  1.1  christos           errno = EBADF;
    372  1.1  christos           return -1;
    373  1.1  christos         }
    374  1.1  christos 
    375  1.1  christos       if (IsSocketHandle (h))
    376  1.1  christos         {
    377  1.1  christos           int requested = FD_CLOSE;
    378  1.1  christos 
    379  1.1  christos           /* See above; socket handles are mapped onto select, but we
    380  1.1  christos              need to map descriptors to handles.  */
    381  1.1  christos           if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    382  1.1  christos             {
    383  1.1  christos               requested |= FD_READ | FD_ACCEPT;
    384  1.1  christos               FD_SET ((SOCKET) h, rfds);
    385  1.1  christos               FD_SET ((SOCKET) h, &handle_rfds);
    386  1.1  christos             }
    387  1.1  christos           if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    388  1.1  christos             {
    389  1.1  christos               requested |= FD_WRITE | FD_CONNECT;
    390  1.1  christos               FD_SET ((SOCKET) h, wfds);
    391  1.1  christos               FD_SET ((SOCKET) h, &handle_wfds);
    392  1.1  christos             }
    393  1.1  christos           if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    394  1.1  christos             {
    395  1.1  christos               requested |= FD_OOB;
    396  1.1  christos               FD_SET ((SOCKET) h, xfds);
    397  1.1  christos               FD_SET ((SOCKET) h, &handle_xfds);
    398  1.1  christos             }
    399  1.1  christos 
    400  1.1  christos           WSAEventSelect ((SOCKET) h, hEvent, requested);
    401  1.1  christos           nsock++;
    402  1.1  christos         }
    403  1.1  christos       else
    404  1.1  christos         {
    405  1.1  christos           handle_array[nhandles++] = h;
    406  1.1  christos 
    407  1.1  christos           /* Poll now.  If we get an event, do not wait below.  */
    408  1.1  christos           if (wait_timeout != 0
    409  1.1  christos               && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
    410  1.1  christos             wait_timeout = 0;
    411  1.1  christos         }
    412  1.1  christos     }
    413  1.1  christos 
    414  1.1  christos   /* Place a sentinel at the end of the array.  */
    415  1.1  christos   handle_array[nhandles] = NULL;
    416  1.1  christos 
    417  1.1  christos   /* When will the waiting period expire?  */
    418  1.1  christos   if (wait_timeout != INFINITE)
    419  1.1  christos     tend = clock () + wait_timeout;
    420  1.1  christos 
    421  1.1  christos restart:
    422  1.1  christos   if (wait_timeout == 0 || nsock == 0)
    423  1.1  christos     rc = 0;
    424  1.1  christos   else
    425  1.1  christos     {
    426  1.1  christos       /* See if we need to wait in the loop below.  If any select is ready,
    427  1.1  christos          do MsgWaitForMultipleObjects anyway to dispatch messages, but
    428  1.1  christos          no need to call select again.  */
    429  1.1  christos       rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
    430  1.1  christos       if (rc == 0)
    431  1.1  christos         {
    432  1.1  christos           /* Restore the fd_sets for the other select we do below.  */
    433  1.1  christos           memcpy (&handle_rfds, rfds, sizeof (fd_set));
    434  1.1  christos           memcpy (&handle_wfds, wfds, sizeof (fd_set));
    435  1.1  christos           memcpy (&handle_xfds, xfds, sizeof (fd_set));
    436  1.1  christos         }
    437  1.1  christos       else
    438  1.1  christos         wait_timeout = 0;
    439  1.1  christos     }
    440  1.1  christos 
    441  1.1  christos   /* How much is left to wait?  */
    442  1.1  christos   if (wait_timeout != INFINITE)
    443  1.1  christos     {
    444  1.1  christos       clock_t tnow = clock ();
    445  1.1  christos       if (tend >= tnow)
    446  1.1  christos         wait_timeout = tend - tnow;
    447  1.1  christos       else
    448  1.1  christos         wait_timeout = 0;
    449  1.1  christos     }
    450  1.1  christos 
    451  1.1  christos   for (;;)
    452  1.1  christos     {
    453  1.1  christos       ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
    454  1.1  christos                                        wait_timeout, QS_ALLINPUT);
    455  1.1  christos 
    456  1.1  christos       if (ret == WAIT_OBJECT_0 + nhandles)
    457  1.1  christos         {
    458  1.1  christos           /* new input of some other kind */
    459  1.1  christos           BOOL bRet;
    460  1.1  christos           while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
    461  1.1  christos             {
    462  1.1  christos               TranslateMessage (&msg);
    463  1.1  christos               DispatchMessage (&msg);
    464  1.1  christos             }
    465  1.1  christos         }
    466  1.1  christos       else
    467  1.1  christos         break;
    468  1.1  christos     }
    469  1.1  christos 
    470  1.1  christos   /* If we haven't done it yet, check the status of the sockets.  */
    471  1.1  christos   if (rc == 0 && nsock > 0)
    472  1.1  christos     rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
    473  1.1  christos 
    474  1.1  christos   if (nhandles > 1)
    475  1.1  christos     {
    476  1.1  christos       /* Count results that are not counted in the return value of select.  */
    477  1.1  christos       nhandles = 1;
    478  1.1  christos       for (i = 0; i < nfds; i++)
    479  1.1  christos         {
    480  1.1  christos           if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
    481  1.1  christos             continue;
    482  1.1  christos 
    483  1.1  christos           h = (HANDLE) _get_osfhandle (i);
    484  1.1  christos           if (h == handle_array[nhandles])
    485  1.1  christos             {
    486  1.1  christos               /* Not a socket.  */
    487  1.1  christos               nhandles++;
    488  1.1  christos               windows_poll_handle (h, i, &rbits, &wbits, &xbits);
    489  1.1  christos               if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
    490  1.1  christos                   || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
    491  1.1  christos                   || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    492  1.1  christos                 rc++;
    493  1.1  christos             }
    494  1.1  christos         }
    495  1.1  christos 
    496  1.1  christos       if (rc == 0
    497  1.1  christos           && (wait_timeout == INFINITE
    498  1.1  christos               /* If NHANDLES > 1, but no bits are set, it means we've
    499  1.1  christos                  been told incorrectly that some handle was signaled.
    500  1.1  christos                  This happens with anonymous pipes, which always cause
    501  1.1  christos                  MsgWaitForMultipleObjects to exit immediately, but no
    502  1.1  christos                  data is found ready to be read by windows_poll_handle.
    503  1.1  christos                  To avoid a total failure (whereby we return zero and
    504  1.1  christos                  don't wait at all), let's poll in a more busy loop.  */
    505  1.1  christos               || (wait_timeout != 0 && nhandles > 1)))
    506  1.1  christos         {
    507  1.1  christos           /* Sleep 1 millisecond to avoid busy wait and retry with the
    508  1.1  christos              original fd_sets.  */
    509  1.1  christos           memcpy (&handle_rfds, rfds, sizeof (fd_set));
    510  1.1  christos           memcpy (&handle_wfds, wfds, sizeof (fd_set));
    511  1.1  christos           memcpy (&handle_xfds, xfds, sizeof (fd_set));
    512  1.1  christos           SleepEx (1, TRUE);
    513  1.1  christos           goto restart;
    514  1.1  christos         }
    515  1.1  christos       if (timeout && wait_timeout == 0 && rc == 0)
    516  1.1  christos         timeout->tv_sec = timeout->tv_usec = 0;
    517  1.1  christos     }
    518  1.1  christos 
    519  1.1  christos   /* Now fill in the results.  */
    520  1.1  christos   FD_ZERO (rfds);
    521  1.1  christos   FD_ZERO (wfds);
    522  1.1  christos   FD_ZERO (xfds);
    523  1.1  christos   nhandles = 1;
    524  1.1  christos   for (i = 0; i < nfds; i++)
    525  1.1  christos     {
    526  1.1  christos       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
    527  1.1  christos         continue;
    528  1.1  christos 
    529  1.1  christos       h = (HANDLE) _get_osfhandle (i);
    530  1.1  christos       if (h != handle_array[nhandles])
    531  1.1  christos         {
    532  1.1  christos           /* Perform handle->descriptor mapping.  */
    533  1.1  christos           SOCKET s = (SOCKET) h;
    534  1.1  christos           WSAEventSelect (s, NULL, 0);
    535  1.1  christos           if (FD_ISSET (s, &handle_rfds))
    536  1.1  christos             FD_SET (i, rfds);
    537  1.1  christos           if (FD_ISSET (s, &handle_wfds))
    538  1.1  christos             FD_SET (i, wfds);
    539  1.1  christos           if (FD_ISSET (s, &handle_xfds))
    540  1.1  christos             FD_SET (i, xfds);
    541  1.1  christos         }
    542  1.1  christos       else
    543  1.1  christos         {
    544  1.1  christos           /* Not a socket.  */
    545  1.1  christos           nhandles++;
    546  1.1  christos           if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    547  1.1  christos             FD_SET (i, rfds);
    548  1.1  christos           if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    549  1.1  christos             FD_SET (i, wfds);
    550  1.1  christos           if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
    551  1.1  christos             FD_SET (i, xfds);
    552  1.1  christos         }
    553  1.1  christos     }
    554  1.1  christos 
    555  1.1  christos   return rc;
    556  1.1  christos }
    557  1.1  christos 
    558  1.1  christos #else /* ! Native Windows.  */
    559  1.1  christos 
    560  1.1  christos #include <stddef.h> /* NULL */
    561  1.1  christos #include <errno.h>
    562  1.1  christos #include <unistd.h>
    563  1.1  christos 
    564  1.1  christos #undef select
    565  1.1  christos 
    566  1.1  christos int
    567  1.1  christos rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
    568  1.1  christos             struct timeval *timeout)
    569  1.1  christos {
    570  1.1  christos   int i;
    571  1.1  christos 
    572  1.1  christos   /* FreeBSD 8.2 has a bug: it does not always detect invalid fds.  */
    573  1.1  christos   if (nfds < 0 || nfds > FD_SETSIZE)
    574  1.1  christos     {
    575  1.1  christos       errno = EINVAL;
    576  1.1  christos       return -1;
    577  1.1  christos     }
    578  1.1  christos   for (i = 0; i < nfds; i++)
    579  1.1  christos     {
    580  1.1  christos       if (((rfds && FD_ISSET (i, rfds))
    581  1.1  christos            || (wfds && FD_ISSET (i, wfds))
    582  1.1  christos            || (xfds && FD_ISSET (i, xfds)))
    583  1.1  christos           && dup2 (i, i) != i)
    584  1.1  christos         return -1;
    585  1.1  christos     }
    586  1.1  christos 
    587  1.1  christos   /* Interix 3.5 has a bug: it does not support nfds == 0.  */
    588  1.1  christos   if (nfds == 0)
    589  1.1  christos     {
    590  1.1  christos       nfds = 1;
    591  1.1  christos       rfds = NULL;
    592  1.1  christos       wfds = NULL;
    593  1.1  christos       xfds = NULL;
    594  1.1  christos     }
    595  1.1  christos   return select (nfds, rfds, wfds, xfds, timeout);
    596  1.1  christos }
    597  1.1  christos 
    598  1.1  christos #endif
    599