1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2019 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 /* Avoid warnings from gcc -Wcast-function-type. */
51 #define GetProcAddress \
52 (void *) GetProcAddress
55 unsigned char in
[FD_SETSIZE
/ CHAR_BIT
];
56 unsigned char out
[FD_SETSIZE
/ CHAR_BIT
];
59 /* Declare data structures for ntdll functions. */
60 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
62 ULONG NamedPipeConfiguration
;
63 ULONG MaximumInstances
;
64 ULONG CurrentInstances
;
66 ULONG ReadDataAvailable
;
68 ULONG WriteQuotaAvailable
;
71 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
73 typedef struct _IO_STATUS_BLOCK
79 ULONG_PTR Information
;
80 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
82 typedef enum _FILE_INFORMATION_CLASS
{
83 FilePipeLocalInformation
= 24
84 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
86 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
87 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
93 static BOOL
IsConsoleHandle (HANDLE h
)
96 return GetConsoleMode (h
, &mode
) != 0;
100 IsSocketHandle (HANDLE h
)
104 if (IsConsoleHandle (h
))
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;
114 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
118 windows_poll_handle (HANDLE h
, int fd
,
119 struct bitset
*rbits
,
120 struct bitset
*wbits
,
121 struct bitset
*xbits
)
123 BOOL read
, write
, except
;
125 INPUT_RECORD
*irbuffer
;
126 DWORD avail
, nbuffer
;
128 IO_STATUS_BLOCK iosb
;
129 FILE_PIPE_LOCAL_INFORMATION fpli
;
130 static PNtQueryInformationFile NtQueryInformationFile
;
131 static BOOL once_only
;
133 read
= write
= except
= FALSE
;
134 switch (GetFileType (h
))
144 NtQueryInformationFile
= (PNtQueryInformationFile
)
145 GetProcAddress (GetModuleHandle ("ntdll.dll"),
146 "NtQueryInformationFile");
150 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
155 else if (GetLastError () == ERROR_BROKEN_PIPE
)
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
168 memset (&iosb
, 0, sizeof (iosb
));
169 memset (&fpli
, 0, sizeof (fpli
));
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
))
183 if (!(rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
186 ret
= WaitForSingleObject (h
, 0);
187 if (ret
== WAIT_OBJECT_0
)
189 if (!IsConsoleHandle (h
))
196 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
198 /* Screen buffers handles are filtered earlier. */
206 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
207 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
208 if (!bRet
|| avail
== 0)
214 for (i
= 0; i
< avail
; i
++)
215 if (irbuffer
[i
].EventType
== KEY_EVENT
)
221 ret
= WaitForSingleObject (h
, 0);
223 if (ret
== WAIT_OBJECT_0
)
230 if (read
&& (rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
232 rbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
236 if (write
&& (wbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
238 wbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
242 if (except
&& (xbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
244 xbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
252 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
253 struct timeval
*timeout
)
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
;
267 if (nfds
> FD_SETSIZE
)
271 wait_timeout
= INFINITE
;
274 wait_timeout
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
276 /* select is also used as a portable usleep. */
277 if (!rfds
&& !wfds
&& !xfds
)
279 Sleep (wait_timeout
);
285 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
287 handle_array
[0] = hEvent
;
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
));
300 for (i
= 0; i
< rfds
->fd_count
; i
++)
302 fd
= rfds
->fd_array
[i
];
303 h
= (HANDLE
) _get_osfhandle (fd
);
304 if (IsConsoleHandle (h
)
305 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
308 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
309 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
312 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
315 for (i
= 0; i
< wfds
->fd_count
; i
++)
317 fd
= wfds
->fd_array
[i
];
318 h
= (HANDLE
) _get_osfhandle (fd
);
319 if (IsConsoleHandle (h
)
320 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
323 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
324 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
327 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
330 for (i
= 0; i
< xfds
->fd_count
; i
++)
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));
337 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
339 /* Zero all the fd_sets, including the application's. */
343 FD_ZERO (&handle_rfds
);
344 FD_ZERO (&handle_wfds
);
345 FD_ZERO (&handle_xfds
);
347 /* Classify handles. Create fd sets for sockets, poll the others. */
348 for (i
= 0; i
< nfds
; i
++)
350 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
353 h
= (HANDLE
) _get_osfhandle (i
);
360 if (IsSocketHandle (h
))
362 int requested
= FD_CLOSE
;
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))))
368 requested
|= FD_READ
| FD_ACCEPT
;
369 FD_SET ((SOCKET
) h
, rfds
);
370 FD_SET ((SOCKET
) h
, &handle_rfds
);
372 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
374 requested
|= FD_WRITE
| FD_CONNECT
;
375 FD_SET ((SOCKET
) h
, wfds
);
376 FD_SET ((SOCKET
) h
, &handle_wfds
);
378 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
381 FD_SET ((SOCKET
) h
, xfds
);
382 FD_SET ((SOCKET
) h
, &handle_xfds
);
385 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
390 handle_array
[nhandles
++] = h
;
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
))
399 /* Place a sentinel at the end of the array. */
400 handle_array
[nhandles
] = NULL
;
402 /* When will the waiting period expire? */
403 if (wait_timeout
!= INFINITE
)
404 tend
= clock () + wait_timeout
;
407 if (wait_timeout
== 0 || nsock
== 0)
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
);
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
));
426 /* How much is left to wait? */
427 if (wait_timeout
!= INFINITE
)
429 clock_t tnow
= clock ();
431 wait_timeout
= tend
- tnow
;
438 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
439 wait_timeout
, QS_ALLINPUT
);
441 if (ret
== WAIT_OBJECT_0
+ nhandles
)
443 /* new input of some other kind */
445 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
447 TranslateMessage (&msg
);
448 DispatchMessage (&msg
);
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
);
461 /* Count results that are not counted in the return value of select. */
463 for (i
= 0; i
< nfds
; i
++)
465 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
468 h
= (HANDLE
) _get_osfhandle (i
);
469 if (h
== handle_array
[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))))
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)))
492 /* Sleep 1 millisecond to avoid busy wait and retry with the
494 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
495 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
496 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
500 if (timeout
&& wait_timeout
== 0 && rc
== 0)
501 timeout
->tv_sec
= timeout
->tv_usec
= 0;
504 /* Now fill in the results. */
509 for (i
= 0; i
< nfds
; i
++)
511 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
514 h
= (HANDLE
) _get_osfhandle (i
);
515 if (h
!= handle_array
[nhandles
])
517 /* Perform handle->descriptor mapping. */
518 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
519 if (FD_ISSET (h
, &handle_rfds
))
521 if (FD_ISSET (h
, &handle_wfds
))
523 if (FD_ISSET (h
, &handle_xfds
))
530 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
532 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
534 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
542 #else /* ! Native Windows. */
544 #include <sys/select.h>
545 #include <stddef.h> /* NULL */
552 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
553 struct timeval
*timeout
)
557 /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
558 if (nfds
< 0 || nfds
> FD_SETSIZE
)
563 for (i
= 0; i
< nfds
; i
++)
565 if (((rfds
&& FD_ISSET (i
, rfds
))
566 || (wfds
&& FD_ISSET (i
, wfds
))
567 || (xfds
&& FD_ISSET (i
, xfds
)))
572 /* Interix 3.5 has a bug: it does not support nfds == 0. */
580 return select (nfds
, rfds
, wfds
, xfds
, timeout
);