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 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, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
29 #include <sys/types.h>
40 #include "msvc-nothrow.h"
43 unsigned char in[FD_SETSIZE / CHAR_BIT];
44 unsigned char out[FD_SETSIZE / CHAR_BIT];
47 /* Declare data structures for ntdll functions. */
48 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
50 ULONG NamedPipeConfiguration;
51 ULONG MaximumInstances;
52 ULONG CurrentInstances;
54 ULONG ReadDataAvailable;
56 ULONG WriteQuotaAvailable;
59 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
61 typedef struct _IO_STATUS_BLOCK
67 ULONG_PTR Information;
68 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
70 typedef enum _FILE_INFORMATION_CLASS {
71 FilePipeLocalInformation = 24
72 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
74 typedef DWORD (WINAPI *PNtQueryInformationFile)
75 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
81 /* Optimized test whether a HANDLE refers to a console.
82 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
83 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
86 IsSocketHandle (HANDLE h)
90 if (IsConsoleHandle (h))
93 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
94 WSAEnumNetworkEvents instead distinguishes the two correctly. */
95 ev.lNetworkEvents = 0xDEADBEEF;
96 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
97 return ev.lNetworkEvents != 0xDEADBEEF;
100 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
103 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
104 struct bitset *xbits)
106 BOOL read, write, except;
108 INPUT_RECORD *irbuffer;
109 DWORD avail, nbuffer;
111 IO_STATUS_BLOCK iosb;
112 FILE_PIPE_LOCAL_INFORMATION fpli;
113 static PNtQueryInformationFile NtQueryInformationFile;
114 static BOOL once_only;
116 read = write = except = FALSE;
117 switch (GetFileType (h))
127 NtQueryInformationFile = (PNtQueryInformationFile)
128 GetProcAddress (GetModuleHandle ("ntdll.dll"),
129 "NtQueryInformationFile");
133 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
138 else if (GetLastError () == ERROR_BROKEN_PIPE)
143 /* It was the write-end of the pipe. Check if it is writable.
144 If NtQueryInformationFile fails, optimistically assume the pipe is
145 writable. This could happen on Win9x, where NtQueryInformationFile
146 is not available, or if we inherit a pipe that doesn't permit
147 FILE_READ_ATTRIBUTES access on the write end (I think this should
148 not happen since WinXP SP2; WINE seems fine too). Otherwise,
149 ensure that enough space is available for atomic writes. */
150 memset (&iosb, 0, sizeof (iosb));
151 memset (&fpli, 0, sizeof (fpli));
153 if (!NtQueryInformationFile
154 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
155 FilePipeLocalInformation)
156 || fpli.WriteQuotaAvailable >= PIPE_BUF
157 || (fpli.OutboundQuota < PIPE_BUF &&
158 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
165 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
168 ret = WaitForSingleObject (h, 0);
169 if (ret == WAIT_OBJECT_0)
171 if (!IsConsoleHandle (h))
178 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
180 /* Screen buffers handles are filtered earlier. */
188 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
189 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
190 if (!bRet || avail == 0)
196 for (i = 0; i < avail; i++)
197 if (irbuffer[i].EventType == KEY_EVENT)
203 ret = WaitForSingleObject (h, 0);
205 if (ret == WAIT_OBJECT_0)
212 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
214 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
218 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
220 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
224 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
226 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
234 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
235 struct timeval *timeout)
237 static struct timeval tv0;
238 static HANDLE hEvent;
239 HANDLE h, handle_array[FD_SETSIZE + 2];
240 fd_set handle_rfds, handle_wfds, handle_xfds;
241 struct bitset rbits, wbits, xbits;
242 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
243 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
247 if (nfds > FD_SETSIZE)
251 wait_timeout = INFINITE;
254 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
256 /* select is also used as a portable usleep. */
257 if (!rfds && !wfds && !xfds)
259 Sleep (wait_timeout);
265 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
267 handle_array[0] = hEvent;
271 /* Copy descriptors to bitsets. At the same time, eliminate
272 bits in the "wrong" direction for console input buffers
273 and screen buffers, because screen buffers are waitable
274 and they will block until a character is available. */
275 memset (&rbits, 0, sizeof (rbits));
276 memset (&wbits, 0, sizeof (wbits));
277 memset (&xbits, 0, sizeof (xbits));
278 memset (anyfds_in, 0, sizeof (anyfds_in));
280 for (i = 0; i < rfds->fd_count; i++)
282 fd = rfds->fd_array[i];
283 h = (HANDLE) _get_osfhandle (fd);
284 if (IsConsoleHandle (h)
285 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
288 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
289 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
292 rfds = (fd_set *) alloca (sizeof (fd_set));
295 for (i = 0; i < wfds->fd_count; i++)
297 fd = wfds->fd_array[i];
298 h = (HANDLE) _get_osfhandle (fd);
299 if (IsConsoleHandle (h)
300 && GetNumberOfConsoleInputEvents (h, &nbuffer))
303 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
304 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
307 wfds = (fd_set *) alloca (sizeof (fd_set));
310 for (i = 0; i < xfds->fd_count; i++)
312 fd = xfds->fd_array[i];
313 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
314 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
317 xfds = (fd_set *) alloca (sizeof (fd_set));
319 /* Zero all the fd_sets, including the application's. */
323 FD_ZERO (&handle_rfds);
324 FD_ZERO (&handle_wfds);
325 FD_ZERO (&handle_xfds);
327 /* Classify handles. Create fd sets for sockets, poll the others. */
328 for (i = 0; i < nfds; i++)
330 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
333 h = (HANDLE) _get_osfhandle (i);
340 if (IsSocketHandle (h))
342 int requested = FD_CLOSE;
344 /* See above; socket handles are mapped onto select, but we
345 need to map descriptors to handles. */
346 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
348 requested |= FD_READ | FD_ACCEPT;
349 FD_SET ((SOCKET) h, rfds);
350 FD_SET ((SOCKET) h, &handle_rfds);
352 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
354 requested |= FD_WRITE | FD_CONNECT;
355 FD_SET ((SOCKET) h, wfds);
356 FD_SET ((SOCKET) h, &handle_wfds);
358 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
361 FD_SET ((SOCKET) h, xfds);
362 FD_SET ((SOCKET) h, &handle_xfds);
365 WSAEventSelect ((SOCKET) h, hEvent, requested);
370 handle_array[nhandles++] = h;
372 /* Poll now. If we get an event, do not wait below. */
373 if (wait_timeout != 0
374 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
379 if (wait_timeout == 0 || nsock == 0)
383 /* See if we need to wait in the loop below. If any select is ready,
384 do MsgWaitForMultipleObjects anyway to dispatch messages, but
385 no need to call select again. */
386 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
389 /* Restore the fd_sets for the other select we do below. */
390 memcpy (&handle_rfds, rfds, sizeof (fd_set));
391 memcpy (&handle_wfds, wfds, sizeof (fd_set));
392 memcpy (&handle_xfds, xfds, sizeof (fd_set));
400 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
401 wait_timeout, QS_ALLINPUT);
403 if (ret == WAIT_OBJECT_0 + nhandles)
405 /* new input of some other kind */
407 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
409 TranslateMessage (&msg);
410 DispatchMessage (&msg);
417 /* If we haven't done it yet, check the status of the sockets. */
418 if (rc == 0 && nsock > 0)
419 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
421 /* Now fill in the results. */
426 /* Place a sentinel at the end of the array. */
427 handle_array[nhandles] = NULL;
429 for (i = 0; i < nfds; i++)
431 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
434 h = (HANDLE) _get_osfhandle (i);
435 if (h != handle_array[nhandles])
437 /* Perform handle->descriptor mapping. Don't update rc, as these
438 results are counted in the return value of Winsock's select. */
439 WSAEventSelect ((SOCKET) h, NULL, 0);
440 if (FD_ISSET (h, &handle_rfds))
442 if (FD_ISSET (h, &handle_wfds))
444 if (FD_ISSET (h, &handle_xfds))
451 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
452 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
457 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
462 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
473 #else /* ! Native Win32. */
475 #include <sys/select.h>
480 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
481 struct timeval *timeout)
483 /* Interix 3.5 has a bug: it does not support nfds == 0. */
491 return select (nfds, rfds, wfds, xfds, timeout);