1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2008-2020 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
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 3, or (at your option)
11 any later version.
12
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.
17
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/>. */
20
21 #include <config.h>
22 #include <alloca.h>
23 #include <assert.h>
24
25 #if defined _WIN32 && ! defined __CYGWIN__
26 /* Native Windows. */
27
28 #include <sys/types.h>
29 #include <errno.h>
30 #include <limits.h>
31
32 #include <winsock2.h>
33 #include <windows.h>
34 #include <io.h>
35 #include <stdio.h>
36 #include <conio.h>
37 #include <time.h>
38
39 /* Get the overridden 'struct timeval'. */
40 #include <sys/time.h>
41
42 #if GNULIB_MSVC_NOTHROW
43 # include "msvc-nothrow.h"
44 #else
45 # include <io.h>
46 #endif
47
48 #undef select
49
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
61
62 /* Avoid warnings from gcc -Wcast-function-type. */
63 #define GetProcAddress \
64 (void *) GetProcAddress
65
66 struct bitset {
67 unsigned char in[FD_SETSIZE / CHAR_BIT];
68 unsigned char out[FD_SETSIZE / CHAR_BIT];
69 };
70
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;
84
85 typedef struct _IO_STATUS_BLOCK
86 {
87 union {
88 DWORD Status;
89 PVOID Pointer;
90 } u;
91 ULONG_PTR Information;
92 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
93
94 typedef enum _FILE_INFORMATION_CLASS {
95 FilePipeLocalInformation = 24
96 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
97
98 typedef DWORD (WINAPI *PNtQueryInformationFile)
99 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
100
101 #ifndef PIPE_BUF
102 #define PIPE_BUF 512
103 #endif
104
IsConsoleHandle(HANDLE h)105 static BOOL IsConsoleHandle (HANDLE h)
106 {
107 DWORD mode;
108 return GetConsoleMode (h, &mode) != 0;
109 }
110
111 static BOOL
IsSocketHandle(HANDLE h)112 IsSocketHandle (HANDLE h)
113 {
114 WSANETWORKEVENTS ev;
115
116 if (IsConsoleHandle (h))
117 return FALSE;
118
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;
124 }
125
126 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
127 H). */
128
129 static int
windows_poll_handle(HANDLE h,int fd,struct bitset * rbits,struct bitset * wbits,struct bitset * xbits)130 windows_poll_handle (HANDLE h, int fd,
131 struct bitset *rbits,
132 struct bitset *wbits,
133 struct bitset *xbits)
134 {
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;
144
145 read = write = except = FALSE;
146 switch (GetFileType (h))
147 {
148 case FILE_TYPE_DISK:
149 read = TRUE;
150 write = TRUE;
151 break;
152
153 case FILE_TYPE_PIPE:
154 if (!once_only)
155 {
156 NtQueryInformationFile = (PNtQueryInformationFile)
157 GetProcAddress (GetModuleHandle ("ntdll.dll"),
158 "NtQueryInformationFile");
159 once_only = TRUE;
160 }
161
162 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
163 {
164 if (avail)
165 read = TRUE;
166 }
167 else if (GetLastError () == ERROR_BROKEN_PIPE)
168 ;
169
170 else
171 {
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));
182
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;
190 }
191 break;
192
193 case FILE_TYPE_CHAR:
194 write = TRUE;
195 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
196 break;
197
198 ret = WaitForSingleObject (h, 0);
199 if (ret == WAIT_OBJECT_0)
200 {
201 if (!IsConsoleHandle (h))
202 {
203 read = TRUE;
204 break;
205 }
206
207 nbuffer = avail = 0;
208 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
209
210 /* Screen buffers handles are filtered earlier. */
211 assert (bRet);
212 if (nbuffer == 0)
213 {
214 except = TRUE;
215 break;
216 }
217
218 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
219 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
220 if (!bRet || avail == 0)
221 {
222 except = TRUE;
223 break;
224 }
225
226 for (i = 0; i < avail; i++)
227 if (irbuffer[i].EventType == KEY_EVENT)
228 read = TRUE;
229 }
230 break;
231
232 default:
233 ret = WaitForSingleObject (h, 0);
234 write = TRUE;
235 if (ret == WAIT_OBJECT_0)
236 read = TRUE;
237
238 break;
239 }
240
241 ret = 0;
242 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
243 {
244 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
245 ret++;
246 }
247
248 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
249 {
250 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
251 ret++;
252 }
253
254 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
255 {
256 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
257 ret++;
258 }
259
260 return ret;
261 }
262
263 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)264 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
265 struct timeval *timeout)
266 #undef timeval
267 {
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;
278
279 if (nfds > FD_SETSIZE)
280 nfds = FD_SETSIZE;
281
282 if (!timeout)
283 wait_timeout = INFINITE;
284 else
285 {
286 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
287
288 /* select is also used as a portable usleep. */
289 if (!rfds && !wfds && !xfds)
290 {
291 Sleep (wait_timeout);
292 return 0;
293 }
294 }
295
296 if (!hEvent)
297 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
298
299 handle_array[0] = hEvent;
300 nhandles = 1;
301 nsock = 0;
302
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++)
313 {
314 fd = rfds->fd_array[i];
315 h = (HANDLE) _get_osfhandle (fd);
316 if (IsConsoleHandle (h)
317 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
318 continue;
319
320 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
321 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
322 }
323 else
324 rfds = (fd_set *) alloca (sizeof (fd_set));
325
326 if (wfds)
327 for (i = 0; i < wfds->fd_count; i++)
328 {
329 fd = wfds->fd_array[i];
330 h = (HANDLE) _get_osfhandle (fd);
331 if (IsConsoleHandle (h)
332 && GetNumberOfConsoleInputEvents (h, &nbuffer))
333 continue;
334
335 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
336 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
337 }
338 else
339 wfds = (fd_set *) alloca (sizeof (fd_set));
340
341 if (xfds)
342 for (i = 0; i < xfds->fd_count; i++)
343 {
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));
347 }
348 else
349 xfds = (fd_set *) alloca (sizeof (fd_set));
350
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);
358
359 /* Classify handles. Create fd sets for sockets, poll the others. */
360 for (i = 0; i < nfds; i++)
361 {
362 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
363 continue;
364
365 h = (HANDLE) _get_osfhandle (i);
366 if (!h)
367 {
368 errno = EBADF;
369 return -1;
370 }
371
372 if (IsSocketHandle (h))
373 {
374 int requested = FD_CLOSE;
375
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))))
379 {
380 requested |= FD_READ | FD_ACCEPT;
381 FD_SET ((SOCKET) h, rfds);
382 FD_SET ((SOCKET) h, &handle_rfds);
383 }
384 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
385 {
386 requested |= FD_WRITE | FD_CONNECT;
387 FD_SET ((SOCKET) h, wfds);
388 FD_SET ((SOCKET) h, &handle_wfds);
389 }
390 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
391 {
392 requested |= FD_OOB;
393 FD_SET ((SOCKET) h, xfds);
394 FD_SET ((SOCKET) h, &handle_xfds);
395 }
396
397 WSAEventSelect ((SOCKET) h, hEvent, requested);
398 nsock++;
399 }
400 else
401 {
402 handle_array[nhandles++] = h;
403
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;
408 }
409 }
410
411 /* Place a sentinel at the end of the array. */
412 handle_array[nhandles] = NULL;
413
414 /* When will the waiting period expire? */
415 if (wait_timeout != INFINITE)
416 tend = clock () + wait_timeout;
417
418 restart:
419 if (wait_timeout == 0 || nsock == 0)
420 rc = 0;
421 else
422 {
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)
428 {
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));
433 }
434 else
435 wait_timeout = 0;
436 }
437
438 /* How much is left to wait? */
439 if (wait_timeout != INFINITE)
440 {
441 clock_t tnow = clock ();
442 if (tend >= tnow)
443 wait_timeout = tend - tnow;
444 else
445 wait_timeout = 0;
446 }
447
448 for (;;)
449 {
450 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
451 wait_timeout, QS_ALLINPUT);
452
453 if (ret == WAIT_OBJECT_0 + nhandles)
454 {
455 /* new input of some other kind */
456 BOOL bRet;
457 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
458 {
459 TranslateMessage (&msg);
460 DispatchMessage (&msg);
461 }
462 }
463 else
464 break;
465 }
466
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);
470
471 if (nhandles > 1)
472 {
473 /* Count results that are not counted in the return value of select. */
474 nhandles = 1;
475 for (i = 0; i < nfds; i++)
476 {
477 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
478 continue;
479
480 h = (HANDLE) _get_osfhandle (i);
481 if (h == handle_array[nhandles])
482 {
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++;
490 }
491 }
492
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)))
503 {
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;
511 }
512 if (timeout && wait_timeout == 0 && rc == 0)
513 timeout->tv_sec = timeout->tv_usec = 0;
514 }
515
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++)
522 {
523 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
524 continue;
525
526 h = (HANDLE) _get_osfhandle (i);
527 if (h != handle_array[nhandles])
528 {
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);
537 }
538 else
539 {
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);
548 }
549 }
550
551 return rc;
552 }
553
554 #else /* ! Native Windows. */
555
556 #include <sys/select.h>
557 #include <stddef.h> /* NULL */
558 #include <errno.h>
559 #include <unistd.h>
560
561 #undef select
562
563 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)564 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
565 struct timeval *timeout)
566 {
567 int i;
568
569 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
570 if (nfds < 0 || nfds > FD_SETSIZE)
571 {
572 errno = EINVAL;
573 return -1;
574 }
575 for (i = 0; i < nfds; i++)
576 {
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;
582 }
583
584 /* Interix 3.5 has a bug: it does not support nfds == 0. */
585 if (nfds == 0)
586 {
587 nfds = 1;
588 rfds = NULL;
589 wfds = NULL;
590 xfds = NULL;
591 }
592 return select (nfds, rfds, wfds, xfds, timeout);
593 }
594
595 #endif
596