1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2008-2019 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 /* Avoid warnings from gcc -Wcast-function-type. */
51 #define GetProcAddress \
52 (void *) GetProcAddress
53
54 struct bitset {
55 unsigned char in[FD_SETSIZE / CHAR_BIT];
56 unsigned char out[FD_SETSIZE / CHAR_BIT];
57 };
58
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;
72
73 typedef struct _IO_STATUS_BLOCK
74 {
75 union {
76 DWORD Status;
77 PVOID Pointer;
78 } u;
79 ULONG_PTR Information;
80 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
81
82 typedef enum _FILE_INFORMATION_CLASS {
83 FilePipeLocalInformation = 24
84 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
85
86 typedef DWORD (WINAPI *PNtQueryInformationFile)
87 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
88
89 #ifndef PIPE_BUF
90 #define PIPE_BUF 512
91 #endif
92
IsConsoleHandle(HANDLE h)93 static BOOL IsConsoleHandle (HANDLE h)
94 {
95 DWORD mode;
96 return GetConsoleMode (h, &mode) != 0;
97 }
98
99 static BOOL
IsSocketHandle(HANDLE h)100 IsSocketHandle (HANDLE h)
101 {
102 WSANETWORKEVENTS ev;
103
104 if (IsConsoleHandle (h))
105 return FALSE;
106
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;
112 }
113
114 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
115 H). */
116
117 static int
windows_poll_handle(HANDLE h,int fd,struct bitset * rbits,struct bitset * wbits,struct bitset * xbits)118 windows_poll_handle (HANDLE h, int fd,
119 struct bitset *rbits,
120 struct bitset *wbits,
121 struct bitset *xbits)
122 {
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;
132
133 read = write = except = FALSE;
134 switch (GetFileType (h))
135 {
136 case FILE_TYPE_DISK:
137 read = TRUE;
138 write = TRUE;
139 break;
140
141 case FILE_TYPE_PIPE:
142 if (!once_only)
143 {
144 NtQueryInformationFile = (PNtQueryInformationFile)
145 GetProcAddress (GetModuleHandle ("ntdll.dll"),
146 "NtQueryInformationFile");
147 once_only = TRUE;
148 }
149
150 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
151 {
152 if (avail)
153 read = TRUE;
154 }
155 else if (GetLastError () == ERROR_BROKEN_PIPE)
156 ;
157
158 else
159 {
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));
170
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;
178 }
179 break;
180
181 case FILE_TYPE_CHAR:
182 write = TRUE;
183 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
184 break;
185
186 ret = WaitForSingleObject (h, 0);
187 if (ret == WAIT_OBJECT_0)
188 {
189 if (!IsConsoleHandle (h))
190 {
191 read = TRUE;
192 break;
193 }
194
195 nbuffer = avail = 0;
196 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
197
198 /* Screen buffers handles are filtered earlier. */
199 assert (bRet);
200 if (nbuffer == 0)
201 {
202 except = TRUE;
203 break;
204 }
205
206 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
207 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
208 if (!bRet || avail == 0)
209 {
210 except = TRUE;
211 break;
212 }
213
214 for (i = 0; i < avail; i++)
215 if (irbuffer[i].EventType == KEY_EVENT)
216 read = TRUE;
217 }
218 break;
219
220 default:
221 ret = WaitForSingleObject (h, 0);
222 write = TRUE;
223 if (ret == WAIT_OBJECT_0)
224 read = TRUE;
225
226 break;
227 }
228
229 ret = 0;
230 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
231 {
232 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
233 ret++;
234 }
235
236 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
237 {
238 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
239 ret++;
240 }
241
242 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
243 {
244 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
245 ret++;
246 }
247
248 return ret;
249 }
250
251 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)252 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
253 struct timeval *timeout)
254 #undef timeval
255 {
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;
266
267 if (nfds > FD_SETSIZE)
268 nfds = FD_SETSIZE;
269
270 if (!timeout)
271 wait_timeout = INFINITE;
272 else
273 {
274 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
275
276 /* select is also used as a portable usleep. */
277 if (!rfds && !wfds && !xfds)
278 {
279 Sleep (wait_timeout);
280 return 0;
281 }
282 }
283
284 if (!hEvent)
285 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
286
287 handle_array[0] = hEvent;
288 nhandles = 1;
289 nsock = 0;
290
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++)
301 {
302 fd = rfds->fd_array[i];
303 h = (HANDLE) _get_osfhandle (fd);
304 if (IsConsoleHandle (h)
305 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
306 continue;
307
308 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
309 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
310 }
311 else
312 rfds = (fd_set *) alloca (sizeof (fd_set));
313
314 if (wfds)
315 for (i = 0; i < wfds->fd_count; i++)
316 {
317 fd = wfds->fd_array[i];
318 h = (HANDLE) _get_osfhandle (fd);
319 if (IsConsoleHandle (h)
320 && GetNumberOfConsoleInputEvents (h, &nbuffer))
321 continue;
322
323 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
325 }
326 else
327 wfds = (fd_set *) alloca (sizeof (fd_set));
328
329 if (xfds)
330 for (i = 0; i < xfds->fd_count; i++)
331 {
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));
335 }
336 else
337 xfds = (fd_set *) alloca (sizeof (fd_set));
338
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);
346
347 /* Classify handles. Create fd sets for sockets, poll the others. */
348 for (i = 0; i < nfds; i++)
349 {
350 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
351 continue;
352
353 h = (HANDLE) _get_osfhandle (i);
354 if (!h)
355 {
356 errno = EBADF;
357 return -1;
358 }
359
360 if (IsSocketHandle (h))
361 {
362 int requested = FD_CLOSE;
363
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))))
367 {
368 requested |= FD_READ | FD_ACCEPT;
369 FD_SET ((SOCKET) h, rfds);
370 FD_SET ((SOCKET) h, &handle_rfds);
371 }
372 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
373 {
374 requested |= FD_WRITE | FD_CONNECT;
375 FD_SET ((SOCKET) h, wfds);
376 FD_SET ((SOCKET) h, &handle_wfds);
377 }
378 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
379 {
380 requested |= FD_OOB;
381 FD_SET ((SOCKET) h, xfds);
382 FD_SET ((SOCKET) h, &handle_xfds);
383 }
384
385 WSAEventSelect ((SOCKET) h, hEvent, requested);
386 nsock++;
387 }
388 else
389 {
390 handle_array[nhandles++] = h;
391
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;
396 }
397 }
398
399 /* Place a sentinel at the end of the array. */
400 handle_array[nhandles] = NULL;
401
402 /* When will the waiting period expire? */
403 if (wait_timeout != INFINITE)
404 tend = clock () + wait_timeout;
405
406 restart:
407 if (wait_timeout == 0 || nsock == 0)
408 rc = 0;
409 else
410 {
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)
416 {
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));
421 }
422 else
423 wait_timeout = 0;
424 }
425
426 /* How much is left to wait? */
427 if (wait_timeout != INFINITE)
428 {
429 clock_t tnow = clock ();
430 if (tend >= tnow)
431 wait_timeout = tend - tnow;
432 else
433 wait_timeout = 0;
434 }
435
436 for (;;)
437 {
438 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
439 wait_timeout, QS_ALLINPUT);
440
441 if (ret == WAIT_OBJECT_0 + nhandles)
442 {
443 /* new input of some other kind */
444 BOOL bRet;
445 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
446 {
447 TranslateMessage (&msg);
448 DispatchMessage (&msg);
449 }
450 }
451 else
452 break;
453 }
454
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);
458
459 if (nhandles > 1)
460 {
461 /* Count results that are not counted in the return value of select. */
462 nhandles = 1;
463 for (i = 0; i < nfds; i++)
464 {
465 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
466 continue;
467
468 h = (HANDLE) _get_osfhandle (i);
469 if (h == handle_array[nhandles])
470 {
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++;
478 }
479 }
480
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)))
491 {
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;
499 }
500 if (timeout && wait_timeout == 0 && rc == 0)
501 timeout->tv_sec = timeout->tv_usec = 0;
502 }
503
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++)
510 {
511 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
512 continue;
513
514 h = (HANDLE) _get_osfhandle (i);
515 if (h != handle_array[nhandles])
516 {
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);
525 }
526 else
527 {
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);
536 }
537 }
538
539 return rc;
540 }
541
542 #else /* ! Native Windows. */
543
544 #include <sys/select.h>
545 #include <stddef.h> /* NULL */
546 #include <errno.h>
547 #include <unistd.h>
548
549 #undef select
550
551 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)552 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
553 struct timeval *timeout)
554 {
555 int i;
556
557 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
558 if (nfds < 0 || nfds > FD_SETSIZE)
559 {
560 errno = EINVAL;
561 return -1;
562 }
563 for (i = 0; i < nfds; i++)
564 {
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;
570 }
571
572 /* Interix 3.5 has a bug: it does not support nfds == 0. */
573 if (nfds == 0)
574 {
575 nfds = 1;
576 rfds = NULL;
577 wfds = NULL;
578 xfds = NULL;
579 }
580 return select (nfds, rfds, wfds, xfds, timeout);
581 }
582
583 #endif
584