1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2008-2018 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 struct bitset {
51 unsigned char in[FD_SETSIZE / CHAR_BIT];
52 unsigned char out[FD_SETSIZE / CHAR_BIT];
53 };
54
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;
68
69 typedef struct _IO_STATUS_BLOCK
70 {
71 union {
72 DWORD Status;
73 PVOID Pointer;
74 } u;
75 ULONG_PTR Information;
76 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
77
78 typedef enum _FILE_INFORMATION_CLASS {
79 FilePipeLocalInformation = 24
80 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
81
82 typedef DWORD (WINAPI *PNtQueryInformationFile)
83 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
84
85 #ifndef PIPE_BUF
86 #define PIPE_BUF 512
87 #endif
88
IsConsoleHandle(HANDLE h)89 static BOOL IsConsoleHandle (HANDLE h)
90 {
91 DWORD mode;
92 return GetConsoleMode (h, &mode) != 0;
93 }
94
95 static BOOL
IsSocketHandle(HANDLE h)96 IsSocketHandle (HANDLE h)
97 {
98 WSANETWORKEVENTS ev;
99
100 if (IsConsoleHandle (h))
101 return FALSE;
102
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;
108 }
109
110 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
111 H). */
112
113 static int
windows_poll_handle(HANDLE h,int fd,struct bitset * rbits,struct bitset * wbits,struct bitset * xbits)114 windows_poll_handle (HANDLE h, int fd,
115 struct bitset *rbits,
116 struct bitset *wbits,
117 struct bitset *xbits)
118 {
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;
128
129 read = write = except = FALSE;
130 switch (GetFileType (h))
131 {
132 case FILE_TYPE_DISK:
133 read = TRUE;
134 write = TRUE;
135 break;
136
137 case FILE_TYPE_PIPE:
138 if (!once_only)
139 {
140 NtQueryInformationFile = (PNtQueryInformationFile)
141 GetProcAddress (GetModuleHandle ("ntdll.dll"),
142 "NtQueryInformationFile");
143 once_only = TRUE;
144 }
145
146 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
147 {
148 if (avail)
149 read = TRUE;
150 }
151 else if (GetLastError () == ERROR_BROKEN_PIPE)
152 ;
153
154 else
155 {
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));
166
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;
174 }
175 break;
176
177 case FILE_TYPE_CHAR:
178 write = TRUE;
179 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
180 break;
181
182 ret = WaitForSingleObject (h, 0);
183 if (ret == WAIT_OBJECT_0)
184 {
185 if (!IsConsoleHandle (h))
186 {
187 read = TRUE;
188 break;
189 }
190
191 nbuffer = avail = 0;
192 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
193
194 /* Screen buffers handles are filtered earlier. */
195 assert (bRet);
196 if (nbuffer == 0)
197 {
198 except = TRUE;
199 break;
200 }
201
202 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
203 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
204 if (!bRet || avail == 0)
205 {
206 except = TRUE;
207 break;
208 }
209
210 for (i = 0; i < avail; i++)
211 if (irbuffer[i].EventType == KEY_EVENT)
212 read = TRUE;
213 }
214 break;
215
216 default:
217 ret = WaitForSingleObject (h, 0);
218 write = TRUE;
219 if (ret == WAIT_OBJECT_0)
220 read = TRUE;
221
222 break;
223 }
224
225 ret = 0;
226 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
227 {
228 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
229 ret++;
230 }
231
232 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
233 {
234 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
235 ret++;
236 }
237
238 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
239 {
240 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
241 ret++;
242 }
243
244 return ret;
245 }
246
247 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)248 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
249 struct timeval *timeout)
250 #undef timeval
251 {
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;
262
263 if (nfds > FD_SETSIZE)
264 nfds = FD_SETSIZE;
265
266 if (!timeout)
267 wait_timeout = INFINITE;
268 else
269 {
270 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
271
272 /* select is also used as a portable usleep. */
273 if (!rfds && !wfds && !xfds)
274 {
275 Sleep (wait_timeout);
276 return 0;
277 }
278 }
279
280 if (!hEvent)
281 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
282
283 handle_array[0] = hEvent;
284 nhandles = 1;
285 nsock = 0;
286
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++)
297 {
298 fd = rfds->fd_array[i];
299 h = (HANDLE) _get_osfhandle (fd);
300 if (IsConsoleHandle (h)
301 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
302 continue;
303
304 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
305 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
306 }
307 else
308 rfds = (fd_set *) alloca (sizeof (fd_set));
309
310 if (wfds)
311 for (i = 0; i < wfds->fd_count; i++)
312 {
313 fd = wfds->fd_array[i];
314 h = (HANDLE) _get_osfhandle (fd);
315 if (IsConsoleHandle (h)
316 && GetNumberOfConsoleInputEvents (h, &nbuffer))
317 continue;
318
319 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
320 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
321 }
322 else
323 wfds = (fd_set *) alloca (sizeof (fd_set));
324
325 if (xfds)
326 for (i = 0; i < xfds->fd_count; i++)
327 {
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));
331 }
332 else
333 xfds = (fd_set *) alloca (sizeof (fd_set));
334
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);
342
343 /* Classify handles. Create fd sets for sockets, poll the others. */
344 for (i = 0; i < nfds; i++)
345 {
346 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
347 continue;
348
349 h = (HANDLE) _get_osfhandle (i);
350 if (!h)
351 {
352 errno = EBADF;
353 return -1;
354 }
355
356 if (IsSocketHandle (h))
357 {
358 int requested = FD_CLOSE;
359
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))))
363 {
364 requested |= FD_READ | FD_ACCEPT;
365 FD_SET ((SOCKET) h, rfds);
366 FD_SET ((SOCKET) h, &handle_rfds);
367 }
368 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
369 {
370 requested |= FD_WRITE | FD_CONNECT;
371 FD_SET ((SOCKET) h, wfds);
372 FD_SET ((SOCKET) h, &handle_wfds);
373 }
374 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
375 {
376 requested |= FD_OOB;
377 FD_SET ((SOCKET) h, xfds);
378 FD_SET ((SOCKET) h, &handle_xfds);
379 }
380
381 WSAEventSelect ((SOCKET) h, hEvent, requested);
382 nsock++;
383 }
384 else
385 {
386 handle_array[nhandles++] = h;
387
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;
392 }
393 }
394
395 /* Place a sentinel at the end of the array. */
396 handle_array[nhandles] = NULL;
397
398 /* When will the waiting period expire? */
399 if (wait_timeout != INFINITE)
400 tend = clock () + wait_timeout;
401
402 restart:
403 if (wait_timeout == 0 || nsock == 0)
404 rc = 0;
405 else
406 {
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)
412 {
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));
417 }
418 else
419 wait_timeout = 0;
420 }
421
422 /* How much is left to wait? */
423 if (wait_timeout != INFINITE)
424 {
425 clock_t tnow = clock ();
426 if (tend >= tnow)
427 wait_timeout = tend - tnow;
428 else
429 wait_timeout = 0;
430 }
431
432 for (;;)
433 {
434 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
435 wait_timeout, QS_ALLINPUT);
436
437 if (ret == WAIT_OBJECT_0 + nhandles)
438 {
439 /* new input of some other kind */
440 BOOL bRet;
441 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
442 {
443 TranslateMessage (&msg);
444 DispatchMessage (&msg);
445 }
446 }
447 else
448 break;
449 }
450
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);
454
455 if (nhandles > 1)
456 {
457 /* Count results that are not counted in the return value of select. */
458 nhandles = 1;
459 for (i = 0; i < nfds; i++)
460 {
461 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
462 continue;
463
464 h = (HANDLE) _get_osfhandle (i);
465 if (h == handle_array[nhandles])
466 {
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++;
474 }
475 }
476
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)))
487 {
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;
495 }
496 if (timeout && wait_timeout == 0 && rc == 0)
497 timeout->tv_sec = timeout->tv_usec = 0;
498 }
499
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++)
506 {
507 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
508 continue;
509
510 h = (HANDLE) _get_osfhandle (i);
511 if (h != handle_array[nhandles])
512 {
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);
521 }
522 else
523 {
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);
532 }
533 }
534
535 return rc;
536 }
537
538 #else /* ! Native Windows. */
539
540 #include <sys/select.h>
541 #include <stddef.h> /* NULL */
542 #include <errno.h>
543 #include <unistd.h>
544
545 #undef select
546
547 int
rpl_select(int nfds,fd_set * rfds,fd_set * wfds,fd_set * xfds,struct timeval * timeout)548 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
549 struct timeval *timeout)
550 {
551 int i;
552
553 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
554 if (nfds < 0 || nfds > FD_SETSIZE)
555 {
556 errno = EINVAL;
557 return -1;
558 }
559 for (i = 0; i < nfds; i++)
560 {
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;
566 }
567
568 /* Interix 3.5 has a bug: it does not support nfds == 0. */
569 if (nfds == 0)
570 {
571 nfds = 1;
572 rfds = NULL;
573 wfds = NULL;
574 xfds = NULL;
575 }
576 return select (nfds, rfds, wfds, xfds, timeout);
577 }
578
579 #endif
580