1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2012 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 3, 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 <http://www.gnu.org/licenses/>. */
25 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
28 #include <sys/types.h>
39 /* Get the overridden 'struct timeval'. */
42 #include "msvc-nothrow.h"
47 unsigned char in
[FD_SETSIZE
/ CHAR_BIT
];
48 unsigned char out
[FD_SETSIZE
/ CHAR_BIT
];
51 /* Declare data structures for ntdll functions. */
52 typedef struct _FILE_PIPE_LOCAL_INFORMATION
{
54 ULONG NamedPipeConfiguration
;
55 ULONG MaximumInstances
;
56 ULONG CurrentInstances
;
58 ULONG ReadDataAvailable
;
60 ULONG WriteQuotaAvailable
;
63 } FILE_PIPE_LOCAL_INFORMATION
, *PFILE_PIPE_LOCAL_INFORMATION
;
65 typedef struct _IO_STATUS_BLOCK
71 ULONG_PTR Information
;
72 } IO_STATUS_BLOCK
, *PIO_STATUS_BLOCK
;
74 typedef enum _FILE_INFORMATION_CLASS
{
75 FilePipeLocalInformation
= 24
76 } FILE_INFORMATION_CLASS
, *PFILE_INFORMATION_CLASS
;
78 typedef DWORD (WINAPI
*PNtQueryInformationFile
)
79 (HANDLE
, IO_STATUS_BLOCK
*, VOID
*, ULONG
, FILE_INFORMATION_CLASS
);
85 /* Optimized test whether a HANDLE refers to a console.
86 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
87 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
90 IsSocketHandle (HANDLE h
)
94 if (IsConsoleHandle (h
))
97 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
98 WSAEnumNetworkEvents instead distinguishes the two correctly. */
99 ev
.lNetworkEvents
= 0xDEADBEEF;
100 WSAEnumNetworkEvents ((SOCKET
) h
, NULL
, &ev
);
101 return ev
.lNetworkEvents
!= 0xDEADBEEF;
104 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
108 windows_poll_handle (HANDLE h
, int fd
,
109 struct bitset
*rbits
,
110 struct bitset
*wbits
,
111 struct bitset
*xbits
)
113 BOOL read
, write
, except
;
115 INPUT_RECORD
*irbuffer
;
116 DWORD avail
, nbuffer
;
118 IO_STATUS_BLOCK iosb
;
119 FILE_PIPE_LOCAL_INFORMATION fpli
;
120 static PNtQueryInformationFile NtQueryInformationFile
;
121 static BOOL once_only
;
123 read
= write
= except
= FALSE
;
124 switch (GetFileType (h
))
134 NtQueryInformationFile
= (PNtQueryInformationFile
)
135 GetProcAddress (GetModuleHandle ("ntdll.dll"),
136 "NtQueryInformationFile");
140 if (PeekNamedPipe (h
, NULL
, 0, NULL
, &avail
, NULL
) != 0)
145 else if (GetLastError () == ERROR_BROKEN_PIPE
)
150 /* It was the write-end of the pipe. Check if it is writable.
151 If NtQueryInformationFile fails, optimistically assume the pipe is
152 writable. This could happen on Windows 9x, where
153 NtQueryInformationFile is not available, or if we inherit a pipe
154 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
155 (I think this should not happen since Windows XP SP2; WINE seems
156 fine too). Otherwise, ensure that enough space is available for
158 memset (&iosb
, 0, sizeof (iosb
));
159 memset (&fpli
, 0, sizeof (fpli
));
161 if (!NtQueryInformationFile
162 || NtQueryInformationFile (h
, &iosb
, &fpli
, sizeof (fpli
),
163 FilePipeLocalInformation
)
164 || fpli
.WriteQuotaAvailable
>= PIPE_BUF
165 || (fpli
.OutboundQuota
< PIPE_BUF
&&
166 fpli
.WriteQuotaAvailable
== fpli
.OutboundQuota
))
173 if (!(rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
176 ret
= WaitForSingleObject (h
, 0);
177 if (ret
== WAIT_OBJECT_0
)
179 if (!IsConsoleHandle (h
))
186 bRet
= GetNumberOfConsoleInputEvents (h
, &nbuffer
);
188 /* Screen buffers handles are filtered earlier. */
196 irbuffer
= (INPUT_RECORD
*) alloca (nbuffer
* sizeof (INPUT_RECORD
));
197 bRet
= PeekConsoleInput (h
, irbuffer
, nbuffer
, &avail
);
198 if (!bRet
|| avail
== 0)
204 for (i
= 0; i
< avail
; i
++)
205 if (irbuffer
[i
].EventType
== KEY_EVENT
)
211 ret
= WaitForSingleObject (h
, 0);
213 if (ret
== WAIT_OBJECT_0
)
220 if (read
&& (rbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
222 rbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
226 if (write
&& (wbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
228 wbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
232 if (except
&& (xbits
->in
[fd
/ CHAR_BIT
] & (1 << (fd
& (CHAR_BIT
- 1)))))
234 xbits
->out
[fd
/ CHAR_BIT
] |= (1 << (fd
& (CHAR_BIT
- 1)));
242 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
243 struct timeval
*timeout
)
246 static struct timeval tv0
;
247 static HANDLE hEvent
;
248 HANDLE h
, handle_array
[FD_SETSIZE
+ 2];
249 fd_set handle_rfds
, handle_wfds
, handle_xfds
;
250 struct bitset rbits
, wbits
, xbits
;
251 unsigned char anyfds_in
[FD_SETSIZE
/ CHAR_BIT
];
252 DWORD ret
, wait_timeout
, nhandles
, nsock
, nbuffer
;
256 if (nfds
> FD_SETSIZE
)
260 wait_timeout
= INFINITE
;
263 wait_timeout
= timeout
->tv_sec
* 1000 + timeout
->tv_usec
/ 1000;
265 /* select is also used as a portable usleep. */
266 if (!rfds
&& !wfds
&& !xfds
)
268 Sleep (wait_timeout
);
274 hEvent
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
276 handle_array
[0] = hEvent
;
280 /* Copy descriptors to bitsets. At the same time, eliminate
281 bits in the "wrong" direction for console input buffers
282 and screen buffers, because screen buffers are waitable
283 and they will block until a character is available. */
284 memset (&rbits
, 0, sizeof (rbits
));
285 memset (&wbits
, 0, sizeof (wbits
));
286 memset (&xbits
, 0, sizeof (xbits
));
287 memset (anyfds_in
, 0, sizeof (anyfds_in
));
289 for (i
= 0; i
< rfds
->fd_count
; i
++)
291 fd
= rfds
->fd_array
[i
];
292 h
= (HANDLE
) _get_osfhandle (fd
);
293 if (IsConsoleHandle (h
)
294 && !GetNumberOfConsoleInputEvents (h
, &nbuffer
))
297 rbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
298 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
301 rfds
= (fd_set
*) alloca (sizeof (fd_set
));
304 for (i
= 0; i
< wfds
->fd_count
; i
++)
306 fd
= wfds
->fd_array
[i
];
307 h
= (HANDLE
) _get_osfhandle (fd
);
308 if (IsConsoleHandle (h
)
309 && GetNumberOfConsoleInputEvents (h
, &nbuffer
))
312 wbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
313 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
316 wfds
= (fd_set
*) alloca (sizeof (fd_set
));
319 for (i
= 0; i
< xfds
->fd_count
; i
++)
321 fd
= xfds
->fd_array
[i
];
322 xbits
.in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
323 anyfds_in
[fd
/ CHAR_BIT
] |= 1 << (fd
& (CHAR_BIT
- 1));
326 xfds
= (fd_set
*) alloca (sizeof (fd_set
));
328 /* Zero all the fd_sets, including the application's. */
332 FD_ZERO (&handle_rfds
);
333 FD_ZERO (&handle_wfds
);
334 FD_ZERO (&handle_xfds
);
336 /* Classify handles. Create fd sets for sockets, poll the others. */
337 for (i
= 0; i
< nfds
; i
++)
339 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
342 h
= (HANDLE
) _get_osfhandle (i
);
349 if (IsSocketHandle (h
))
351 int requested
= FD_CLOSE
;
353 /* See above; socket handles are mapped onto select, but we
354 need to map descriptors to handles. */
355 if (rbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
357 requested
|= FD_READ
| FD_ACCEPT
;
358 FD_SET ((SOCKET
) h
, rfds
);
359 FD_SET ((SOCKET
) h
, &handle_rfds
);
361 if (wbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
363 requested
|= FD_WRITE
| FD_CONNECT
;
364 FD_SET ((SOCKET
) h
, wfds
);
365 FD_SET ((SOCKET
) h
, &handle_wfds
);
367 if (xbits
.in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
370 FD_SET ((SOCKET
) h
, xfds
);
371 FD_SET ((SOCKET
) h
, &handle_xfds
);
374 WSAEventSelect ((SOCKET
) h
, hEvent
, requested
);
379 handle_array
[nhandles
++] = h
;
381 /* Poll now. If we get an event, do not wait below. */
382 if (wait_timeout
!= 0
383 && windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
))
388 /* Place a sentinel at the end of the array. */
389 handle_array
[nhandles
] = NULL
;
392 if (wait_timeout
== 0 || nsock
== 0)
396 /* See if we need to wait in the loop below. If any select is ready,
397 do MsgWaitForMultipleObjects anyway to dispatch messages, but
398 no need to call select again. */
399 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
402 /* Restore the fd_sets for the other select we do below. */
403 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
404 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
405 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
413 ret
= MsgWaitForMultipleObjects (nhandles
, handle_array
, FALSE
,
414 wait_timeout
, QS_ALLINPUT
);
416 if (ret
== WAIT_OBJECT_0
+ nhandles
)
418 /* new input of some other kind */
420 while ((bRet
= PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) != 0)
422 TranslateMessage (&msg
);
423 DispatchMessage (&msg
);
430 /* If we haven't done it yet, check the status of the sockets. */
431 if (rc
== 0 && nsock
> 0)
432 rc
= select (0, &handle_rfds
, &handle_wfds
, &handle_xfds
, &tv0
);
436 /* Count results that are not counted in the return value of select. */
438 for (i
= 0; i
< nfds
; i
++)
440 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
443 h
= (HANDLE
) _get_osfhandle (i
);
444 if (h
== handle_array
[nhandles
])
448 windows_poll_handle (h
, i
, &rbits
, &wbits
, &xbits
);
449 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
450 || wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))
451 || xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
456 if (rc
== 0 && wait_timeout
== INFINITE
)
458 /* Sleep 1 millisecond to avoid busy wait and retry with the
460 memcpy (&handle_rfds
, rfds
, sizeof (fd_set
));
461 memcpy (&handle_wfds
, wfds
, sizeof (fd_set
));
462 memcpy (&handle_xfds
, xfds
, sizeof (fd_set
));
468 /* Now fill in the results. */
473 for (i
= 0; i
< nfds
; i
++)
475 if ((anyfds_in
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1)))) == 0)
478 h
= (HANDLE
) _get_osfhandle (i
);
479 if (h
!= handle_array
[nhandles
])
481 /* Perform handle->descriptor mapping. */
482 WSAEventSelect ((SOCKET
) h
, NULL
, 0);
483 if (FD_ISSET (h
, &handle_rfds
))
485 if (FD_ISSET (h
, &handle_wfds
))
487 if (FD_ISSET (h
, &handle_xfds
))
494 if (rbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
496 if (wbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
498 if (xbits
.out
[i
/ CHAR_BIT
] & (1 << (i
& (CHAR_BIT
- 1))))
506 #else /* ! Native Windows. */
508 #include <sys/select.h>
509 #include <stddef.h> /* NULL */
514 rpl_select (int nfds
, fd_set
*rfds
, fd_set
*wfds
, fd_set
*xfds
,
515 struct timeval
*timeout
)
517 /* Interix 3.5 has a bug: it does not support nfds == 0. */
525 return select (nfds
, rfds
, wfds
, xfds
, timeout
);