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