fstat: Fix module dependency conditions.
[gnulib/ericb.git] / lib / select.c
blob01b19823fbd68a92fd669999250cf777b052b646
1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2017 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 <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <alloca.h>
23 #include <assert.h>
25 #if (defined _WIN32 || 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 struct bitset {
51 unsigned char in[FD_SETSIZE / CHAR_BIT];
52 unsigned char out[FD_SETSIZE / CHAR_BIT];
55 /* Declare data structures for ntdll functions. */
56 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
57 ULONG NamedPipeType;
58 ULONG NamedPipeConfiguration;
59 ULONG MaximumInstances;
60 ULONG CurrentInstances;
61 ULONG InboundQuota;
62 ULONG ReadDataAvailable;
63 ULONG OutboundQuota;
64 ULONG WriteQuotaAvailable;
65 ULONG NamedPipeState;
66 ULONG NamedPipeEnd;
67 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
69 typedef struct _IO_STATUS_BLOCK
71 union {
72 DWORD Status;
73 PVOID Pointer;
74 } u;
75 ULONG_PTR Information;
76 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
78 typedef enum _FILE_INFORMATION_CLASS {
79 FilePipeLocalInformation = 24
80 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
82 typedef DWORD (WINAPI *PNtQueryInformationFile)
83 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
85 #ifndef PIPE_BUF
86 #define PIPE_BUF 512
87 #endif
89 static BOOL IsConsoleHandle (HANDLE h)
91 DWORD mode;
92 return GetConsoleMode (h, &mode) != 0;
95 static BOOL
96 IsSocketHandle (HANDLE h)
98 WSANETWORKEVENTS ev;
100 if (IsConsoleHandle (h))
101 return FALSE;
103 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
104 WSAEnumNetworkEvents instead distinguishes the two correctly. */
105 ev.lNetworkEvents = 0xDEADBEEF;
106 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
107 return ev.lNetworkEvents != 0xDEADBEEF;
110 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
111 H). */
113 static int
114 windows_poll_handle (HANDLE h, int fd,
115 struct bitset *rbits,
116 struct bitset *wbits,
117 struct bitset *xbits)
119 BOOL read, write, except;
120 int i, ret;
121 INPUT_RECORD *irbuffer;
122 DWORD avail, nbuffer;
123 BOOL bRet;
124 IO_STATUS_BLOCK iosb;
125 FILE_PIPE_LOCAL_INFORMATION fpli;
126 static PNtQueryInformationFile NtQueryInformationFile;
127 static BOOL once_only;
129 read = write = except = FALSE;
130 switch (GetFileType (h))
132 case FILE_TYPE_DISK:
133 read = TRUE;
134 write = TRUE;
135 break;
137 case FILE_TYPE_PIPE:
138 if (!once_only)
140 NtQueryInformationFile = (PNtQueryInformationFile)
141 GetProcAddress (GetModuleHandle ("ntdll.dll"),
142 "NtQueryInformationFile");
143 once_only = TRUE;
146 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
148 if (avail)
149 read = TRUE;
151 else if (GetLastError () == ERROR_BROKEN_PIPE)
154 else
156 /* It was the write-end of the pipe. Check if it is writable.
157 If NtQueryInformationFile fails, optimistically assume the pipe is
158 writable. This could happen on Windows 9x, where
159 NtQueryInformationFile is not available, or if we inherit a pipe
160 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
161 (I think this should not happen since Windows XP SP2; WINE seems
162 fine too). Otherwise, ensure that enough space is available for
163 atomic writes. */
164 memset (&iosb, 0, sizeof (iosb));
165 memset (&fpli, 0, sizeof (fpli));
167 if (!NtQueryInformationFile
168 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
169 FilePipeLocalInformation)
170 || fpli.WriteQuotaAvailable >= PIPE_BUF
171 || (fpli.OutboundQuota < PIPE_BUF &&
172 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
173 write = TRUE;
175 break;
177 case FILE_TYPE_CHAR:
178 write = TRUE;
179 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
180 break;
182 ret = WaitForSingleObject (h, 0);
183 if (ret == WAIT_OBJECT_0)
185 if (!IsConsoleHandle (h))
187 read = TRUE;
188 break;
191 nbuffer = avail = 0;
192 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
194 /* Screen buffers handles are filtered earlier. */
195 assert (bRet);
196 if (nbuffer == 0)
198 except = TRUE;
199 break;
202 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
203 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
204 if (!bRet || avail == 0)
206 except = TRUE;
207 break;
210 for (i = 0; i < avail; i++)
211 if (irbuffer[i].EventType == KEY_EVENT)
212 read = TRUE;
214 break;
216 default:
217 ret = WaitForSingleObject (h, 0);
218 write = TRUE;
219 if (ret == WAIT_OBJECT_0)
220 read = TRUE;
222 break;
225 ret = 0;
226 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
228 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
229 ret++;
232 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
234 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
235 ret++;
238 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
240 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
241 ret++;
244 return ret;
248 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
249 struct timeval *timeout)
250 #undef timeval
252 static struct timeval tv0;
253 static HANDLE hEvent;
254 HANDLE h, handle_array[FD_SETSIZE + 2];
255 fd_set handle_rfds, handle_wfds, handle_xfds;
256 struct bitset rbits, wbits, xbits;
257 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
258 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
259 MSG msg;
260 int i, fd, rc;
261 clock_t tend;
263 if (nfds > FD_SETSIZE)
264 nfds = FD_SETSIZE;
266 if (!timeout)
267 wait_timeout = INFINITE;
268 else
270 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
272 /* select is also used as a portable usleep. */
273 if (!rfds && !wfds && !xfds)
275 Sleep (wait_timeout);
276 return 0;
280 if (!hEvent)
281 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
283 handle_array[0] = hEvent;
284 nhandles = 1;
285 nsock = 0;
287 /* Copy descriptors to bitsets. At the same time, eliminate
288 bits in the "wrong" direction for console input buffers
289 and screen buffers, because screen buffers are waitable
290 and they will block until a character is available. */
291 memset (&rbits, 0, sizeof (rbits));
292 memset (&wbits, 0, sizeof (wbits));
293 memset (&xbits, 0, sizeof (xbits));
294 memset (anyfds_in, 0, sizeof (anyfds_in));
295 if (rfds)
296 for (i = 0; i < rfds->fd_count; i++)
298 fd = rfds->fd_array[i];
299 h = (HANDLE) _get_osfhandle (fd);
300 if (IsConsoleHandle (h)
301 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
302 continue;
304 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
305 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
307 else
308 rfds = (fd_set *) alloca (sizeof (fd_set));
310 if (wfds)
311 for (i = 0; i < wfds->fd_count; i++)
313 fd = wfds->fd_array[i];
314 h = (HANDLE) _get_osfhandle (fd);
315 if (IsConsoleHandle (h)
316 && GetNumberOfConsoleInputEvents (h, &nbuffer))
317 continue;
319 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
320 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
322 else
323 wfds = (fd_set *) alloca (sizeof (fd_set));
325 if (xfds)
326 for (i = 0; i < xfds->fd_count; i++)
328 fd = xfds->fd_array[i];
329 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
330 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
332 else
333 xfds = (fd_set *) alloca (sizeof (fd_set));
335 /* Zero all the fd_sets, including the application's. */
336 FD_ZERO (rfds);
337 FD_ZERO (wfds);
338 FD_ZERO (xfds);
339 FD_ZERO (&handle_rfds);
340 FD_ZERO (&handle_wfds);
341 FD_ZERO (&handle_xfds);
343 /* Classify handles. Create fd sets for sockets, poll the others. */
344 for (i = 0; i < nfds; i++)
346 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
347 continue;
349 h = (HANDLE) _get_osfhandle (i);
350 if (!h)
352 errno = EBADF;
353 return -1;
356 if (IsSocketHandle (h))
358 int requested = FD_CLOSE;
360 /* See above; socket handles are mapped onto select, but we
361 need to map descriptors to handles. */
362 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
364 requested |= FD_READ | FD_ACCEPT;
365 FD_SET ((SOCKET) h, rfds);
366 FD_SET ((SOCKET) h, &handle_rfds);
368 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
370 requested |= FD_WRITE | FD_CONNECT;
371 FD_SET ((SOCKET) h, wfds);
372 FD_SET ((SOCKET) h, &handle_wfds);
374 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
376 requested |= FD_OOB;
377 FD_SET ((SOCKET) h, xfds);
378 FD_SET ((SOCKET) h, &handle_xfds);
381 WSAEventSelect ((SOCKET) h, hEvent, requested);
382 nsock++;
384 else
386 handle_array[nhandles++] = h;
388 /* Poll now. If we get an event, do not wait below. */
389 if (wait_timeout != 0
390 && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
391 wait_timeout = 0;
395 /* Place a sentinel at the end of the array. */
396 handle_array[nhandles] = NULL;
398 /* When will the waiting period expire? */
399 if (wait_timeout != INFINITE)
400 tend = clock () + wait_timeout;
402 restart:
403 if (wait_timeout == 0 || nsock == 0)
404 rc = 0;
405 else
407 /* See if we need to wait in the loop below. If any select is ready,
408 do MsgWaitForMultipleObjects anyway to dispatch messages, but
409 no need to call select again. */
410 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
411 if (rc == 0)
413 /* Restore the fd_sets for the other select we do below. */
414 memcpy (&handle_rfds, rfds, sizeof (fd_set));
415 memcpy (&handle_wfds, wfds, sizeof (fd_set));
416 memcpy (&handle_xfds, xfds, sizeof (fd_set));
418 else
419 wait_timeout = 0;
422 /* How much is left to wait? */
423 if (wait_timeout != INFINITE)
425 clock_t tnow = clock ();
426 if (tend >= tnow)
427 wait_timeout = tend - tnow;
428 else
429 wait_timeout = 0;
432 for (;;)
434 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
435 wait_timeout, QS_ALLINPUT);
437 if (ret == WAIT_OBJECT_0 + nhandles)
439 /* new input of some other kind */
440 BOOL bRet;
441 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
443 TranslateMessage (&msg);
444 DispatchMessage (&msg);
447 else
448 break;
451 /* If we haven't done it yet, check the status of the sockets. */
452 if (rc == 0 && nsock > 0)
453 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
455 if (nhandles > 1)
457 /* Count results that are not counted in the return value of select. */
458 nhandles = 1;
459 for (i = 0; i < nfds; i++)
461 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
462 continue;
464 h = (HANDLE) _get_osfhandle (i);
465 if (h == handle_array[nhandles])
467 /* Not a socket. */
468 nhandles++;
469 windows_poll_handle (h, i, &rbits, &wbits, &xbits);
470 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
471 || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
472 || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
473 rc++;
477 if (rc == 0
478 && (wait_timeout == INFINITE
479 /* If NHANDLES > 1, but no bits are set, it means we've
480 been told incorrectly that some handle was signaled.
481 This happens with anonymous pipes, which always cause
482 MsgWaitForMultipleObjects to exit immediately, but no
483 data is found ready to be read by windows_poll_handle.
484 To avoid a total failure (whereby we return zero and
485 don't wait at all), let's poll in a more busy loop. */
486 || (wait_timeout != 0 && nhandles > 1)))
488 /* Sleep 1 millisecond to avoid busy wait and retry with the
489 original fd_sets. */
490 memcpy (&handle_rfds, rfds, sizeof (fd_set));
491 memcpy (&handle_wfds, wfds, sizeof (fd_set));
492 memcpy (&handle_xfds, xfds, sizeof (fd_set));
493 SleepEx (1, TRUE);
494 goto restart;
496 if (timeout && wait_timeout == 0 && rc == 0)
497 timeout->tv_sec = timeout->tv_usec = 0;
500 /* Now fill in the results. */
501 FD_ZERO (rfds);
502 FD_ZERO (wfds);
503 FD_ZERO (xfds);
504 nhandles = 1;
505 for (i = 0; i < nfds; i++)
507 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
508 continue;
510 h = (HANDLE) _get_osfhandle (i);
511 if (h != handle_array[nhandles])
513 /* Perform handle->descriptor mapping. */
514 WSAEventSelect ((SOCKET) h, NULL, 0);
515 if (FD_ISSET (h, &handle_rfds))
516 FD_SET (i, rfds);
517 if (FD_ISSET (h, &handle_wfds))
518 FD_SET (i, wfds);
519 if (FD_ISSET (h, &handle_xfds))
520 FD_SET (i, xfds);
522 else
524 /* Not a socket. */
525 nhandles++;
526 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
527 FD_SET (i, rfds);
528 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
529 FD_SET (i, wfds);
530 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
531 FD_SET (i, xfds);
535 return rc;
538 #else /* ! Native Windows. */
540 #include <sys/select.h>
541 #include <stddef.h> /* NULL */
542 #include <errno.h>
543 #include <unistd.h>
545 #undef select
548 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
549 struct timeval *timeout)
551 int i;
553 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
554 if (nfds < 0 || nfds > FD_SETSIZE)
556 errno = EINVAL;
557 return -1;
559 for (i = 0; i < nfds; i++)
561 if (((rfds && FD_ISSET (i, rfds))
562 || (wfds && FD_ISSET (i, wfds))
563 || (xfds && FD_ISSET (i, xfds)))
564 && dup2 (i, i) != i)
565 return -1;
568 /* Interix 3.5 has a bug: it does not support nfds == 0. */
569 if (nfds == 0)
571 nfds = 1;
572 rfds = NULL;
573 wfds = NULL;
574 xfds = NULL;
576 return select (nfds, rfds, wfds, xfds, timeout);
579 #endif