1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2020 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)
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/>. */
25 #if defined _WIN32 && ! defined __CYGWIN__
28 #include <sys/types.h>
39 /* Get the overridden 'struct timeval'. */
42 #if GNULIB_MSVC_NOTHROW
43 # include "msvc-nothrow.h"
50 /* Don't assume that UNICODE is not defined. */
51 #undef GetModuleHandle
52 #define GetModuleHandle GetModuleHandleA
53 #undef PeekConsoleInput
54 #define PeekConsoleInput PeekConsoleInputA
56 #define CreateEvent CreateEventA
58 #define PeekMessage PeekMessageA
59 #undef DispatchMessage
60 #define DispatchMessage DispatchMessageA
62 /* Avoid warnings from gcc -Wcast-function-type. */
63 #define GetProcAddress \
64 (void *) GetProcAddress
67 unsigned char in
[FD_SETSIZE
/ CHAR_BIT
];
68 unsigned char out
[FD_SETSIZE
/ CHAR_BIT
];
71 /* Declare data structures for ntdll functions. */
72 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
74 ULONG NamedPipeConfiguration
;
75 ULONG MaximumInstances
;
76 ULONG CurrentInstances
;
78 ULONG ReadDataAvailable
;
80 ULONG WriteQuotaAvailable
;
83 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
85 typedef struct _IO_STATUS_BLOCK
91 ULONG_PTR Information
;
92 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
94 typedef enum _FILE_INFORMATION_CLASS
{
95 FilePipeLocalInformation
= 24
96 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
98 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
99 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
105 static BOOL
IsConsoleHandle (HANDLE h
)
108 return GetConsoleMode (h
, &mode
) != 0;
112 IsSocketHandle (HANDLE h
)
116 if (IsConsoleHandle (h
))
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;
126 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
130 windows_poll_handle (HANDLE h
, int fd
,
131 struct bitset
*rbits
,
132 struct bitset
*wbits
,
133 struct bitset
*xbits
)
135 BOOL read
, write
, except
;
137 INPUT_RECORD
*irbuffer
;
138 DWORD avail
, nbuffer
;
140 IO_STATUS_BLOCK iosb
;
141 FILE_PIPE_LOCAL_INFORMATION fpli
;
142 static PNtQueryInformationFile NtQueryInformationFile
;
143 static BOOL once_only
;
145 read
= write
= except
= FALSE
;
146 switch (GetFileType (h
))
156 NtQueryInformationFile
= (PNtQueryInformationFile
)
157 GetProcAddress (GetModuleHandle ("ntdll.dll"),
158 "NtQueryInformationFile");
162 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
167 else if (GetLastError () == ERROR_BROKEN_PIPE
)
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
180 memset (&iosb
, 0, sizeof (iosb
));
181 memset (&fpli
, 0, sizeof (fpli
));
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
))
195 if (!(rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
198 ret
= WaitForSingleObject (h
, 0);
199 if (ret
== WAIT_OBJECT_0
)
201 if (!IsConsoleHandle (h
))
208 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
210 /* Screen buffers handles are filtered earlier. */
218 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
219 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
220 if (!bRet
|| avail
== 0)
226 for (i
= 0; i
< avail
; i
++)
227 if (irbuffer
[i
].EventType
== KEY_EVENT
)
233 ret
= WaitForSingleObject (h
, 0);
235 if (ret
== WAIT_OBJECT_0
)
242 if (read
&& (rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
244 rbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
248 if (write
&& (wbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
250 wbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
254 if (except
&& (xbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
256 xbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
264 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
265 struct timeval
*timeout
)
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
;
279 if (nfds
> FD_SETSIZE
)
283 wait_timeout
= INFINITE
;
286 wait_timeout
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
288 /* select is also used as a portable usleep. */
289 if (!rfds
&& !wfds
&& !xfds
)
291 Sleep (wait_timeout
);
297 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
299 handle_array
[0] = hEvent
;
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
));
312 for (i
= 0; i
< rfds
->fd_count
; i
++)
314 fd
= rfds
->fd_array
[i
];
315 h
= (HANDLE
) _get_osfhandle (fd
);
316 if (IsConsoleHandle (h
)
317 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
320 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
321 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
324 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
327 for (i
= 0; i
< wfds
->fd_count
; i
++)
329 fd
= wfds
->fd_array
[i
];
330 h
= (HANDLE
) _get_osfhandle (fd
);
331 if (IsConsoleHandle (h
)
332 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
335 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
336 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
339 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
342 for (i
= 0; i
< xfds
->fd_count
; i
++)
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));
349 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
351 /* Zero all the fd_sets, including the application's. */
355 FD_ZERO (&handle_rfds
);
356 FD_ZERO (&handle_wfds
);
357 FD_ZERO (&handle_xfds
);
359 /* Classify handles. Create fd sets for sockets, poll the others. */
360 for (i
= 0; i
< nfds
; i
++)
362 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
365 h
= (HANDLE
) _get_osfhandle (i
);
372 if (IsSocketHandle (h
))
374 int requested
= FD_CLOSE
;
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))))
380 requested
|= FD_READ
| FD_ACCEPT
;
381 FD_SET ((SOCKET
) h
, rfds
);
382 FD_SET ((SOCKET
) h
, &handle_rfds
);
384 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
386 requested
|= FD_WRITE
| FD_CONNECT
;
387 FD_SET ((SOCKET
) h
, wfds
);
388 FD_SET ((SOCKET
) h
, &handle_wfds
);
390 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
393 FD_SET ((SOCKET
) h
, xfds
);
394 FD_SET ((SOCKET
) h
, &handle_xfds
);
397 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
402 handle_array
[nhandles
++] = h
;
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
))
411 /* Place a sentinel at the end of the array. */
412 handle_array
[nhandles
] = NULL
;
414 /* When will the waiting period expire? */
415 if (wait_timeout
!= INFINITE
)
416 tend
= clock () + wait_timeout
;
419 if (wait_timeout
== 0 || nsock
== 0)
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
);
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
));
438 /* How much is left to wait? */
439 if (wait_timeout
!= INFINITE
)
441 clock_t tnow
= clock ();
443 wait_timeout
= tend
- tnow
;
450 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
451 wait_timeout
, QS_ALLINPUT
);
453 if (ret
== WAIT_OBJECT_0
+ nhandles
)
455 /* new input of some other kind */
457 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
459 TranslateMessage (&msg
);
460 DispatchMessage (&msg
);
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
);
473 /* Count results that are not counted in the return value of select. */
475 for (i
= 0; i
< nfds
; i
++)
477 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
480 h
= (HANDLE
) _get_osfhandle (i
);
481 if (h
== handle_array
[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))))
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)))
504 /* Sleep 1 millisecond to avoid busy wait and retry with the
506 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
507 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
508 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
512 if (timeout
&& wait_timeout
== 0 && rc
== 0)
513 timeout
->tv_sec
= timeout
->tv_usec
= 0;
516 /* Now fill in the results. */
521 for (i
= 0; i
< nfds
; i
++)
523 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
526 h
= (HANDLE
) _get_osfhandle (i
);
527 if (h
!= handle_array
[nhandles
])
529 /* Perform handle->descriptor mapping. */
530 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
531 if (FD_ISSET (h
, &handle_rfds
))
533 if (FD_ISSET (h
, &handle_wfds
))
535 if (FD_ISSET (h
, &handle_xfds
))
542 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
544 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
546 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
554 #else /* ! Native Windows. */
556 #include <sys/select.h>
557 #include <stddef.h> /* NULL */
564 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
565 struct timeval
*timeout
)
569 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
570 if (nfds
< 0 || nfds
> FD_SETSIZE
)
575 for (i
= 0; i
< nfds
; i
++)
577 if (((rfds
&& FD_ISSET (i
, rfds
))
578 || (wfds
&& FD_ISSET (i
, wfds
))
579 || (xfds
&& FD_ISSET (i
, xfds
)))
584 /* Interix 3.5 has a bug: it does not support nfds == 0. */
592 return select (nfds
, rfds
, wfds
, xfds
, timeout
);