Avoid -Wcast-function-type warnings from casts after GetProcAddress.
[gnulib.git] / lib / select.c
blobffb58ee4dbb033dcc0231e0fd350451d059f1527
1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2018 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 /* Avoid warnings from gcc -Wcast-function-type. */
51 #define GetProcAddress \
52 (void *) GetProcAddress
54 struct bitset {
55 unsigned char in[FD_SETSIZE / CHAR_BIT];
56 unsigned char out[FD_SETSIZE / CHAR_BIT];
59 /* Declare data structures for ntdll functions. */
60 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
61 ULONG NamedPipeType;
62 ULONG NamedPipeConfiguration;
63 ULONG MaximumInstances;
64 ULONG CurrentInstances;
65 ULONG InboundQuota;
66 ULONG ReadDataAvailable;
67 ULONG OutboundQuota;
68 ULONG WriteQuotaAvailable;
69 ULONG NamedPipeState;
70 ULONG NamedPipeEnd;
71 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
73 typedef struct _IO_STATUS_BLOCK
75 union {
76 DWORD Status;
77 PVOID Pointer;
78 } u;
79 ULONG_PTR Information;
80 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
82 typedef enum _FILE_INFORMATION_CLASS {
83 FilePipeLocalInformation = 24
84 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
86 typedef DWORD (WINAPI *PNtQueryInformationFile)
87 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
89 #ifndef PIPE_BUF
90 #define PIPE_BUF 512
91 #endif
93 static BOOL IsConsoleHandle (HANDLE h)
95 DWORD mode;
96 return GetConsoleMode (h, &mode) != 0;
99 static BOOL
100 IsSocketHandle (HANDLE h)
102 WSANETWORKEVENTS ev;
104 if (IsConsoleHandle (h))
105 return FALSE;
107 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
108 WSAEnumNetworkEvents instead distinguishes the two correctly. */
109 ev.lNetworkEvents = 0xDEADBEEF;
110 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
111 return ev.lNetworkEvents != 0xDEADBEEF;
114 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
115 H). */
117 static int
118 windows_poll_handle (HANDLE h, int fd,
119 struct bitset *rbits,
120 struct bitset *wbits,
121 struct bitset *xbits)
123 BOOL read, write, except;
124 int i, ret;
125 INPUT_RECORD *irbuffer;
126 DWORD avail, nbuffer;
127 BOOL bRet;
128 IO_STATUS_BLOCK iosb;
129 FILE_PIPE_LOCAL_INFORMATION fpli;
130 static PNtQueryInformationFile NtQueryInformationFile;
131 static BOOL once_only;
133 read = write = except = FALSE;
134 switch (GetFileType (h))
136 case FILE_TYPE_DISK:
137 read = TRUE;
138 write = TRUE;
139 break;
141 case FILE_TYPE_PIPE:
142 if (!once_only)
144 NtQueryInformationFile = (PNtQueryInformationFile)
145 GetProcAddress (GetModuleHandle ("ntdll.dll"),
146 "NtQueryInformationFile");
147 once_only = TRUE;
150 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
152 if (avail)
153 read = TRUE;
155 else if (GetLastError () == ERROR_BROKEN_PIPE)
158 else
160 /* It was the write-end of the pipe. Check if it is writable.
161 If NtQueryInformationFile fails, optimistically assume the pipe is
162 writable. This could happen on Windows 9x, where
163 NtQueryInformationFile is not available, or if we inherit a pipe
164 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
165 (I think this should not happen since Windows XP SP2; WINE seems
166 fine too). Otherwise, ensure that enough space is available for
167 atomic writes. */
168 memset (&iosb, 0, sizeof (iosb));
169 memset (&fpli, 0, sizeof (fpli));
171 if (!NtQueryInformationFile
172 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
173 FilePipeLocalInformation)
174 || fpli.WriteQuotaAvailable >= PIPE_BUF
175 || (fpli.OutboundQuota < PIPE_BUF &&
176 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
177 write = TRUE;
179 break;
181 case FILE_TYPE_CHAR:
182 write = TRUE;
183 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
184 break;
186 ret = WaitForSingleObject (h, 0);
187 if (ret == WAIT_OBJECT_0)
189 if (!IsConsoleHandle (h))
191 read = TRUE;
192 break;
195 nbuffer = avail = 0;
196 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
198 /* Screen buffers handles are filtered earlier. */
199 assert (bRet);
200 if (nbuffer == 0)
202 except = TRUE;
203 break;
206 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
207 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
208 if (!bRet || avail == 0)
210 except = TRUE;
211 break;
214 for (i = 0; i < avail; i++)
215 if (irbuffer[i].EventType == KEY_EVENT)
216 read = TRUE;
218 break;
220 default:
221 ret = WaitForSingleObject (h, 0);
222 write = TRUE;
223 if (ret == WAIT_OBJECT_0)
224 read = TRUE;
226 break;
229 ret = 0;
230 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
232 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
233 ret++;
236 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
238 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
239 ret++;
242 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
244 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
245 ret++;
248 return ret;
252 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
253 struct timeval *timeout)
254 #undef timeval
256 static struct timeval tv0;
257 static HANDLE hEvent;
258 HANDLE h, handle_array[FD_SETSIZE + 2];
259 fd_set handle_rfds, handle_wfds, handle_xfds;
260 struct bitset rbits, wbits, xbits;
261 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
262 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
263 MSG msg;
264 int i, fd, rc;
265 clock_t tend;
267 if (nfds > FD_SETSIZE)
268 nfds = FD_SETSIZE;
270 if (!timeout)
271 wait_timeout = INFINITE;
272 else
274 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
276 /* select is also used as a portable usleep. */
277 if (!rfds && !wfds && !xfds)
279 Sleep (wait_timeout);
280 return 0;
284 if (!hEvent)
285 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
287 handle_array[0] = hEvent;
288 nhandles = 1;
289 nsock = 0;
291 /* Copy descriptors to bitsets. At the same time, eliminate
292 bits in the "wrong" direction for console input buffers
293 and screen buffers, because screen buffers are waitable
294 and they will block until a character is available. */
295 memset (&rbits, 0, sizeof (rbits));
296 memset (&wbits, 0, sizeof (wbits));
297 memset (&xbits, 0, sizeof (xbits));
298 memset (anyfds_in, 0, sizeof (anyfds_in));
299 if (rfds)
300 for (i = 0; i < rfds->fd_count; i++)
302 fd = rfds->fd_array[i];
303 h = (HANDLE) _get_osfhandle (fd);
304 if (IsConsoleHandle (h)
305 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
306 continue;
308 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
309 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
311 else
312 rfds = (fd_set *) alloca (sizeof (fd_set));
314 if (wfds)
315 for (i = 0; i < wfds->fd_count; i++)
317 fd = wfds->fd_array[i];
318 h = (HANDLE) _get_osfhandle (fd);
319 if (IsConsoleHandle (h)
320 && GetNumberOfConsoleInputEvents (h, &nbuffer))
321 continue;
323 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
326 else
327 wfds = (fd_set *) alloca (sizeof (fd_set));
329 if (xfds)
330 for (i = 0; i < xfds->fd_count; i++)
332 fd = xfds->fd_array[i];
333 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
334 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
336 else
337 xfds = (fd_set *) alloca (sizeof (fd_set));
339 /* Zero all the fd_sets, including the application's. */
340 FD_ZERO (rfds);
341 FD_ZERO (wfds);
342 FD_ZERO (xfds);
343 FD_ZERO (&handle_rfds);
344 FD_ZERO (&handle_wfds);
345 FD_ZERO (&handle_xfds);
347 /* Classify handles. Create fd sets for sockets, poll the others. */
348 for (i = 0; i < nfds; i++)
350 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
351 continue;
353 h = (HANDLE) _get_osfhandle (i);
354 if (!h)
356 errno = EBADF;
357 return -1;
360 if (IsSocketHandle (h))
362 int requested = FD_CLOSE;
364 /* See above; socket handles are mapped onto select, but we
365 need to map descriptors to handles. */
366 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
368 requested |= FD_READ | FD_ACCEPT;
369 FD_SET ((SOCKET) h, rfds);
370 FD_SET ((SOCKET) h, &handle_rfds);
372 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
374 requested |= FD_WRITE | FD_CONNECT;
375 FD_SET ((SOCKET) h, wfds);
376 FD_SET ((SOCKET) h, &handle_wfds);
378 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
380 requested |= FD_OOB;
381 FD_SET ((SOCKET) h, xfds);
382 FD_SET ((SOCKET) h, &handle_xfds);
385 WSAEventSelect ((SOCKET) h, hEvent, requested);
386 nsock++;
388 else
390 handle_array[nhandles++] = h;
392 /* Poll now. If we get an event, do not wait below. */
393 if (wait_timeout != 0
394 && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
395 wait_timeout = 0;
399 /* Place a sentinel at the end of the array. */
400 handle_array[nhandles] = NULL;
402 /* When will the waiting period expire? */
403 if (wait_timeout != INFINITE)
404 tend = clock () + wait_timeout;
406 restart:
407 if (wait_timeout == 0 || nsock == 0)
408 rc = 0;
409 else
411 /* See if we need to wait in the loop below. If any select is ready,
412 do MsgWaitForMultipleObjects anyway to dispatch messages, but
413 no need to call select again. */
414 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
415 if (rc == 0)
417 /* Restore the fd_sets for the other select we do below. */
418 memcpy (&handle_rfds, rfds, sizeof (fd_set));
419 memcpy (&handle_wfds, wfds, sizeof (fd_set));
420 memcpy (&handle_xfds, xfds, sizeof (fd_set));
422 else
423 wait_timeout = 0;
426 /* How much is left to wait? */
427 if (wait_timeout != INFINITE)
429 clock_t tnow = clock ();
430 if (tend >= tnow)
431 wait_timeout = tend - tnow;
432 else
433 wait_timeout = 0;
436 for (;;)
438 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
439 wait_timeout, QS_ALLINPUT);
441 if (ret == WAIT_OBJECT_0 + nhandles)
443 /* new input of some other kind */
444 BOOL bRet;
445 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
447 TranslateMessage (&msg);
448 DispatchMessage (&msg);
451 else
452 break;
455 /* If we haven't done it yet, check the status of the sockets. */
456 if (rc == 0 && nsock > 0)
457 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
459 if (nhandles > 1)
461 /* Count results that are not counted in the return value of select. */
462 nhandles = 1;
463 for (i = 0; i < nfds; i++)
465 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
466 continue;
468 h = (HANDLE) _get_osfhandle (i);
469 if (h == handle_array[nhandles])
471 /* Not a socket. */
472 nhandles++;
473 windows_poll_handle (h, i, &rbits, &wbits, &xbits);
474 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
475 || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
476 || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
477 rc++;
481 if (rc == 0
482 && (wait_timeout == INFINITE
483 /* If NHANDLES > 1, but no bits are set, it means we've
484 been told incorrectly that some handle was signaled.
485 This happens with anonymous pipes, which always cause
486 MsgWaitForMultipleObjects to exit immediately, but no
487 data is found ready to be read by windows_poll_handle.
488 To avoid a total failure (whereby we return zero and
489 don't wait at all), let's poll in a more busy loop. */
490 || (wait_timeout != 0 && nhandles > 1)))
492 /* Sleep 1 millisecond to avoid busy wait and retry with the
493 original fd_sets. */
494 memcpy (&handle_rfds, rfds, sizeof (fd_set));
495 memcpy (&handle_wfds, wfds, sizeof (fd_set));
496 memcpy (&handle_xfds, xfds, sizeof (fd_set));
497 SleepEx (1, TRUE);
498 goto restart;
500 if (timeout && wait_timeout == 0 && rc == 0)
501 timeout->tv_sec = timeout->tv_usec = 0;
504 /* Now fill in the results. */
505 FD_ZERO (rfds);
506 FD_ZERO (wfds);
507 FD_ZERO (xfds);
508 nhandles = 1;
509 for (i = 0; i < nfds; i++)
511 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
512 continue;
514 h = (HANDLE) _get_osfhandle (i);
515 if (h != handle_array[nhandles])
517 /* Perform handle->descriptor mapping. */
518 WSAEventSelect ((SOCKET) h, NULL, 0);
519 if (FD_ISSET (h, &handle_rfds))
520 FD_SET (i, rfds);
521 if (FD_ISSET (h, &handle_wfds))
522 FD_SET (i, wfds);
523 if (FD_ISSET (h, &handle_xfds))
524 FD_SET (i, xfds);
526 else
528 /* Not a socket. */
529 nhandles++;
530 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
531 FD_SET (i, rfds);
532 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
533 FD_SET (i, wfds);
534 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
535 FD_SET (i, xfds);
539 return rc;
542 #else /* ! Native Windows. */
544 #include <sys/select.h>
545 #include <stddef.h> /* NULL */
546 #include <errno.h>
547 #include <unistd.h>
549 #undef select
552 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
553 struct timeval *timeout)
555 int i;
557 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
558 if (nfds < 0 || nfds > FD_SETSIZE)
560 errno = EINVAL;
561 return -1;
563 for (i = 0; i < nfds; i++)
565 if (((rfds && FD_ISSET (i, rfds))
566 || (wfds && FD_ISSET (i, wfds))
567 || (xfds && FD_ISSET (i, xfds)))
568 && dup2 (i, i) != i)
569 return -1;
572 /* Interix 3.5 has a bug: it does not support nfds == 0. */
573 if (nfds == 0)
575 nfds = 1;
576 rfds = NULL;
577 wfds = NULL;
578 xfds = NULL;
580 return select (nfds, rfds, wfds, xfds, timeout);
583 #endif