1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2022 Free Software Foundation, Inc.
6 This file is part of gnulib.
8 This file is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 This file 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 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>. */
24 #include <sys/select.h>
26 #if defined _WIN32 && ! defined __CYGWIN__
31 #include <sys/types.h>
42 /* Get the overridden 'struct timeval'. */
45 #if GNULIB_MSVC_NOTHROW
46 # include "msvc-nothrow.h"
53 /* Don't assume that UNICODE is not defined. */
54 #undef GetModuleHandle
55 #define GetModuleHandle GetModuleHandleA
56 #undef PeekConsoleInput
57 #define PeekConsoleInput PeekConsoleInputA
59 #define CreateEvent CreateEventA
61 #define PeekMessage PeekMessageA
62 #undef DispatchMessage
63 #define DispatchMessage DispatchMessageA
65 /* Avoid warnings from gcc -Wcast-function-type. */
66 #define GetProcAddress \
67 (void *) GetProcAddress
70 unsigned char in
[FD_SETSIZE
/ CHAR_BIT
];
71 unsigned char out
[FD_SETSIZE
/ CHAR_BIT
];
74 /* Declare data structures for ntdll functions. */
75 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
77 ULONG NamedPipeConfiguration
;
78 ULONG MaximumInstances
;
79 ULONG CurrentInstances
;
81 ULONG ReadDataAvailable
;
83 ULONG WriteQuotaAvailable
;
86 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
88 typedef struct _IO_STATUS_BLOCK
94 ULONG_PTR Information
;
95 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
97 typedef enum _FILE_INFORMATION_CLASS
{
98 FilePipeLocalInformation
= 24
99 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
101 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
102 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
108 static BOOL
IsConsoleHandle (HANDLE h
)
111 return GetConsoleMode (h
, &mode
) != 0;
115 IsSocketHandle (HANDLE h
)
119 if (IsConsoleHandle (h
))
122 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
123 WSAEnumNetworkEvents instead distinguishes the two correctly. */
124 ev
.lNetworkEvents
= 0xDEADBEEF;
125 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
126 return ev
.lNetworkEvents
!= 0xDEADBEEF;
129 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
133 windows_poll_handle (HANDLE h
, int fd
,
134 struct bitset
*rbits
,
135 struct bitset
*wbits
,
136 struct bitset
*xbits
)
138 BOOL read
, write
, except
;
140 INPUT_RECORD
*irbuffer
;
141 DWORD avail
, nbuffer
;
143 IO_STATUS_BLOCK iosb
;
144 FILE_PIPE_LOCAL_INFORMATION fpli
;
145 static PNtQueryInformationFile NtQueryInformationFile
;
146 static BOOL once_only
;
148 read
= write
= except
= FALSE
;
149 switch (GetFileType (h
))
159 NtQueryInformationFile
= (PNtQueryInformationFile
)
160 GetProcAddress (GetModuleHandle ("ntdll.dll"),
161 "NtQueryInformationFile");
165 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
170 else if (GetLastError () == ERROR_BROKEN_PIPE
)
175 /* It was the write-end of the pipe. Check if it is writable.
176 If NtQueryInformationFile fails, optimistically assume the pipe is
177 writable. This could happen on Windows 9x, where
178 NtQueryInformationFile is not available, or if we inherit a pipe
179 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
180 (I think this should not happen since Windows XP SP2; WINE seems
181 fine too). Otherwise, ensure that enough space is available for
183 memset (&iosb
, 0, sizeof (iosb
));
184 memset (&fpli
, 0, sizeof (fpli
));
186 if (!NtQueryInformationFile
187 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
188 FilePipeLocalInformation
)
189 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
190 || (fpli
.OutboundQuota
< PIPE_BUF
&&
191 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
198 if (!(rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
201 ret
= WaitForSingleObject (h
, 0);
202 if (ret
== WAIT_OBJECT_0
)
204 if (!IsConsoleHandle (h
))
211 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
213 /* Screen buffers handles are filtered earlier. */
221 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
222 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
223 if (!bRet
|| avail
== 0)
229 for (i
= 0; i
< avail
; i
++)
230 if (irbuffer
[i
].EventType
== KEY_EVENT
)
236 ret
= WaitForSingleObject (h
, 0);
238 if (ret
== WAIT_OBJECT_0
)
245 if (read
&& (rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
247 rbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
251 if (write
&& (wbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
253 wbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
257 if (except
&& (xbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
259 xbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
267 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
268 struct timeval
*timeout
)
271 static struct timeval tv0
;
272 static HANDLE hEvent
;
273 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
274 fd_set handle_rfds
, handle_wfds
, handle_xfds
;
275 struct bitset rbits
, wbits
, xbits
;
276 unsigned char anyfds_in
[FD_SETSIZE
/ CHAR_BIT
];
277 DWORD ret
, wait_timeout
, nhandles
, nsock
, nbuffer
;
282 if (nfds
> FD_SETSIZE
)
286 wait_timeout
= INFINITE
;
289 wait_timeout
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
291 /* select is also used as a portable usleep. */
292 if (!rfds
&& !wfds
&& !xfds
)
294 Sleep (wait_timeout
);
300 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
302 handle_array
[0] = hEvent
;
306 /* Copy descriptors to bitsets. At the same time, eliminate
307 bits in the "wrong" direction for console input buffers
308 and screen buffers, because screen buffers are waitable
309 and they will block until a character is available. */
310 memset (&rbits
, 0, sizeof (rbits
));
311 memset (&wbits
, 0, sizeof (wbits
));
312 memset (&xbits
, 0, sizeof (xbits
));
313 memset (anyfds_in
, 0, sizeof (anyfds_in
));
315 for (i
= 0; i
< rfds
->fd_count
; i
++)
317 fd
= rfds
->fd_array
[i
];
318 h
= (HANDLE
) _get_osfhandle (fd
);
319 if (IsConsoleHandle (h
)
320 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
323 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
324 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
327 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
330 for (i
= 0; i
< wfds
->fd_count
; i
++)
332 fd
= wfds
->fd_array
[i
];
333 h
= (HANDLE
) _get_osfhandle (fd
);
334 if (IsConsoleHandle (h
)
335 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
338 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
339 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
342 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
345 for (i
= 0; i
< xfds
->fd_count
; i
++)
347 fd
= xfds
->fd_array
[i
];
348 xbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
349 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
352 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
354 /* Zero all the fd_sets, including the application's. */
358 FD_ZERO (&handle_rfds
);
359 FD_ZERO (&handle_wfds
);
360 FD_ZERO (&handle_xfds
);
362 /* Classify handles. Create fd sets for sockets, poll the others. */
363 for (i
= 0; i
< nfds
; i
++)
365 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
368 h
= (HANDLE
) _get_osfhandle (i
);
375 if (IsSocketHandle (h
))
377 int requested
= FD_CLOSE
;
379 /* See above; socket handles are mapped onto select, but we
380 need to map descriptors to handles. */
381 if (rbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
383 requested
|= FD_READ
| FD_ACCEPT
;
384 FD_SET ((SOCKET
) h
, rfds
);
385 FD_SET ((SOCKET
) h
, &handle_rfds
);
387 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
389 requested
|= FD_WRITE
| FD_CONNECT
;
390 FD_SET ((SOCKET
) h
, wfds
);
391 FD_SET ((SOCKET
) h
, &handle_wfds
);
393 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
396 FD_SET ((SOCKET
) h
, xfds
);
397 FD_SET ((SOCKET
) h
, &handle_xfds
);
400 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
405 handle_array
[nhandles
++] = h
;
407 /* Poll now. If we get an event, do not wait below. */
408 if (wait_timeout
!= 0
409 && windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
))
414 /* Place a sentinel at the end of the array. */
415 handle_array
[nhandles
] = NULL
;
417 /* When will the waiting period expire? */
418 if (wait_timeout
!= INFINITE
)
419 tend
= clock () + wait_timeout
;
422 if (wait_timeout
== 0 || nsock
== 0)
426 /* See if we need to wait in the loop below. If any select is ready,
427 do MsgWaitForMultipleObjects anyway to dispatch messages, but
428 no need to call select again. */
429 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
432 /* Restore the fd_sets for the other select we do below. */
433 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
434 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
435 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
441 /* How much is left to wait? */
442 if (wait_timeout
!= INFINITE
)
444 clock_t tnow
= clock ();
446 wait_timeout
= tend
- tnow
;
453 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
454 wait_timeout
, QS_ALLINPUT
);
456 if (ret
== WAIT_OBJECT_0
+ nhandles
)
458 /* new input of some other kind */
460 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
462 TranslateMessage (&msg
);
463 DispatchMessage (&msg
);
470 /* If we haven't done it yet, check the status of the sockets. */
471 if (rc
== 0 && nsock
> 0)
472 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
476 /* Count results that are not counted in the return value of select. */
478 for (i
= 0; i
< nfds
; i
++)
480 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
483 h
= (HANDLE
) _get_osfhandle (i
);
484 if (h
== handle_array
[nhandles
])
488 windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
);
489 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
490 || wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
491 || xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
497 && (wait_timeout
== INFINITE
498 /* If NHANDLES > 1, but no bits are set, it means we've
499 been told incorrectly that some handle was signaled.
500 This happens with anonymous pipes, which always cause
501 MsgWaitForMultipleObjects to exit immediately, but no
502 data is found ready to be read by windows_poll_handle.
503 To avoid a total failure (whereby we return zero and
504 don't wait at all), let's poll in a more busy loop. */
505 || (wait_timeout
!= 0 && nhandles
> 1)))
507 /* Sleep 1 millisecond to avoid busy wait and retry with the
509 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
510 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
511 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
515 if (timeout
&& wait_timeout
== 0 && rc
== 0)
516 timeout
->tv_sec
= timeout
->tv_usec
= 0;
519 /* Now fill in the results. */
524 for (i
= 0; i
< nfds
; i
++)
526 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
529 h
= (HANDLE
) _get_osfhandle (i
);
530 if (h
!= handle_array
[nhandles
])
532 /* Perform handle->descriptor mapping. */
533 SOCKET s
= (SOCKET
) h
;
534 WSAEventSelect (s
, NULL
, 0);
535 if (FD_ISSET (s
, &handle_rfds
))
537 if (FD_ISSET (s
, &handle_wfds
))
539 if (FD_ISSET (s
, &handle_xfds
))
546 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
548 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
550 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
558 #else /* ! Native Windows. */
560 #include <stddef.h> /* NULL */
567 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
568 struct timeval
*timeout
)
572 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
573 if (nfds
< 0 || nfds
> FD_SETSIZE
)
578 for (i
= 0; i
< nfds
; i
++)
580 if (((rfds
&& FD_ISSET (i
, rfds
))
581 || (wfds
&& FD_ISSET (i
, wfds
))
582 || (xfds
&& FD_ISSET (i
, xfds
)))
587 /* Interix 3.5 has a bug: it does not support nfds == 0. */
595 return select (nfds
, rfds
, wfds
, xfds
, timeout
);