1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2025 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
< 0 || nfds
> FD_SETSIZE
)
289 wait_timeout
= INFINITE
;
292 wait_timeout
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
294 /* select is also used as a portable usleep. */
295 if (!rfds
&& !wfds
&& !xfds
)
297 Sleep (wait_timeout
);
303 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
305 handle_array
[0] = hEvent
;
309 /* Copy descriptors to bitsets. At the same time, eliminate
310 bits in the "wrong" direction for console input buffers
311 and screen buffers, because screen buffers are waitable
312 and they will block until a character is available. */
313 memset (&rbits
, 0, sizeof (rbits
));
314 memset (&wbits
, 0, sizeof (wbits
));
315 memset (&xbits
, 0, sizeof (xbits
));
316 memset (anyfds_in
, 0, sizeof (anyfds_in
));
318 for (i
= 0; i
< rfds
->fd_count
; i
++)
320 fd
= rfds
->fd_array
[i
];
321 h
= (HANDLE
) _get_osfhandle (fd
);
322 if (IsConsoleHandle (h
)
323 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
326 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
327 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
330 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
333 for (i
= 0; i
< wfds
->fd_count
; i
++)
335 fd
= wfds
->fd_array
[i
];
336 h
= (HANDLE
) _get_osfhandle (fd
);
337 if (IsConsoleHandle (h
)
338 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
341 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
342 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
345 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
348 for (i
= 0; i
< xfds
->fd_count
; i
++)
350 fd
= xfds
->fd_array
[i
];
351 xbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
352 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
355 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
357 /* Zero all the fd_sets, including the application's. */
361 FD_ZERO (&handle_rfds
);
362 FD_ZERO (&handle_wfds
);
363 FD_ZERO (&handle_xfds
);
365 /* Classify handles. Create fd sets for sockets, poll the others. */
366 for (i
= 0; i
< nfds
; i
++)
368 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
371 h
= (HANDLE
) _get_osfhandle (i
);
378 if (IsSocketHandle (h
))
380 int requested
= FD_CLOSE
;
382 /* See above; socket handles are mapped onto select, but we
383 need to map descriptors to handles. */
384 if (rbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
386 requested
|= FD_READ
| FD_ACCEPT
;
387 FD_SET ((SOCKET
) h
, rfds
);
388 FD_SET ((SOCKET
) h
, &handle_rfds
);
390 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
392 requested
|= FD_WRITE
| FD_CONNECT
;
393 FD_SET ((SOCKET
) h
, wfds
);
394 FD_SET ((SOCKET
) h
, &handle_wfds
);
396 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
399 FD_SET ((SOCKET
) h
, xfds
);
400 FD_SET ((SOCKET
) h
, &handle_xfds
);
403 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
408 handle_array
[nhandles
++] = h
;
410 /* Poll now. If we get an event, do not wait below. */
411 if (wait_timeout
!= 0
412 && windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
))
417 /* Place a sentinel at the end of the array. */
418 handle_array
[nhandles
] = NULL
;
420 /* When will the waiting period expire? */
421 if (wait_timeout
!= INFINITE
)
422 tend
= clock () + wait_timeout
;
425 if (wait_timeout
== 0 || nsock
== 0)
429 /* See if we need to wait in the loop below. If any select is ready,
430 do MsgWaitForMultipleObjects anyway to dispatch messages, but
431 no need to call select again. */
432 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
435 /* Restore the fd_sets for the other select we do below. */
436 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
437 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
438 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
444 /* How much is left to wait? */
445 if (wait_timeout
!= INFINITE
)
447 clock_t tnow
= clock ();
449 wait_timeout
= tend
- tnow
;
456 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
457 wait_timeout
, QS_ALLINPUT
);
459 if (ret
== WAIT_OBJECT_0
+ nhandles
)
461 /* new input of some other kind */
463 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
465 TranslateMessage (&msg
);
466 DispatchMessage (&msg
);
473 /* If we haven't done it yet, check the status of the sockets. */
474 if (rc
== 0 && nsock
> 0)
475 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
479 /* Count results that are not counted in the return value of select. */
481 for (i
= 0; i
< nfds
; i
++)
483 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
486 h
= (HANDLE
) _get_osfhandle (i
);
487 if (h
== handle_array
[nhandles
])
491 windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
);
492 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
493 || wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
494 || xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
500 && (wait_timeout
== INFINITE
501 /* If NHANDLES > 1, but no bits are set, it means we've
502 been told incorrectly that some handle was signaled.
503 This happens with anonymous pipes, which always cause
504 MsgWaitForMultipleObjects to exit immediately, but no
505 data is found ready to be read by windows_poll_handle.
506 To avoid a total failure (whereby we return zero and
507 don't wait at all), let's poll in a more busy loop. */
508 || (wait_timeout
!= 0 && nhandles
> 1)))
510 /* Sleep 1 millisecond to avoid busy wait and retry with the
512 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
513 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
514 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
518 if (timeout
&& wait_timeout
== 0 && rc
== 0)
519 timeout
->tv_sec
= timeout
->tv_usec
= 0;
522 /* Now fill in the results. */
527 for (i
= 0; i
< nfds
; i
++)
529 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
532 h
= (HANDLE
) _get_osfhandle (i
);
533 if (h
!= handle_array
[nhandles
])
535 /* Perform handle->descriptor mapping. */
536 SOCKET s
= (SOCKET
) h
;
537 WSAEventSelect (s
, NULL
, 0);
538 if (FD_ISSET (s
, &handle_rfds
))
540 if (FD_ISSET (s
, &handle_wfds
))
542 if (FD_ISSET (s
, &handle_xfds
))
549 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
551 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
553 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
561 #else /* ! Native Windows. */
563 #include <stddef.h> /* NULL */
570 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
571 struct timeval
*timeout
)
575 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
576 if (nfds
< 0 || nfds
> FD_SETSIZE
)
581 for (i
= 0; i
< nfds
; i
++)
583 if (((rfds
&& FD_ISSET (i
, rfds
))
584 || (wfds
&& FD_ISSET (i
, wfds
))
585 || (xfds
&& FD_ISSET (i
, xfds
)))
590 /* Interix 3.5 has a bug: it does not support nfds == 0. */
598 return select (nfds
, rfds
, wfds
, xfds
, timeout
);