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