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