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 Windows handle is
104 windows_poll_handle (HANDLE h, int fd,
105 struct bitset *rbits,
106 struct bitset *wbits,
107 struct bitset *xbits)
109 BOOL read, write, except;
111 INPUT_RECORD *irbuffer;
112 DWORD avail, nbuffer;
114 IO_STATUS_BLOCK iosb;
115 FILE_PIPE_LOCAL_INFORMATION fpli;
116 static PNtQueryInformationFile NtQueryInformationFile;
117 static BOOL once_only;
119 read = write = except = FALSE;
120 switch (GetFileType (h))
130 NtQueryInformationFile = (PNtQueryInformationFile)
131 GetProcAddress (GetModuleHandle ("ntdll.dll"),
132 "NtQueryInformationFile");
136 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
141 else if (GetLastError () == ERROR_BROKEN_PIPE)
146 /* It was the write-end of the pipe. Check if it is writable.
147 If NtQueryInformationFile fails, optimistically assume the pipe is
148 writable. This could happen on Windows 9x, where
149 NtQueryInformationFile is not available, or if we inherit a pipe
150 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
151 (I think this should not happen since Windows XP SP2; WINE seems
152 fine too). Otherwise, ensure that enough space is available for
154 memset (&iosb, 0, sizeof (iosb));
155 memset (&fpli, 0, sizeof (fpli));
157 if (!NtQueryInformationFile
158 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
159 FilePipeLocalInformation)
160 || fpli.WriteQuotaAvailable >= PIPE_BUF
161 || (fpli.OutboundQuota < PIPE_BUF &&
162 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
169 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
172 ret = WaitForSingleObject (h, 0);
173 if (ret == WAIT_OBJECT_0)
175 if (!IsConsoleHandle (h))
182 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
184 /* Screen buffers handles are filtered earlier. */
192 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
193 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
194 if (!bRet || avail == 0)
200 for (i = 0; i < avail; i++)
201 if (irbuffer[i].EventType == KEY_EVENT)
207 ret = WaitForSingleObject (h, 0);
209 if (ret == WAIT_OBJECT_0)
216 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
218 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
222 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
224 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
228 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
230 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
238 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
239 struct timeval *timeout)
241 static struct timeval tv0;
242 static HANDLE hEvent;
243 HANDLE h, handle_array[FD_SETSIZE + 2];
244 fd_set handle_rfds, handle_wfds, handle_xfds;
245 struct bitset rbits, wbits, xbits;
246 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
247 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
251 if (nfds > FD_SETSIZE)
255 wait_timeout = INFINITE;
258 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
260 /* select is also used as a portable usleep. */
261 if (!rfds && !wfds && !xfds)
263 Sleep (wait_timeout);
269 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
271 handle_array[0] = hEvent;
275 /* Copy descriptors to bitsets. At the same time, eliminate
276 bits in the "wrong" direction for console input buffers
277 and screen buffers, because screen buffers are waitable
278 and they will block until a character is available. */
279 memset (&rbits, 0, sizeof (rbits));
280 memset (&wbits, 0, sizeof (wbits));
281 memset (&xbits, 0, sizeof (xbits));
282 memset (anyfds_in, 0, sizeof (anyfds_in));
284 for (i = 0; i < rfds->fd_count; i++)
286 fd = rfds->fd_array[i];
287 h = (HANDLE) _get_osfhandle (fd);
288 if (IsConsoleHandle (h)
289 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
292 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
293 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
296 rfds = (fd_set *) alloca (sizeof (fd_set));
299 for (i = 0; i < wfds->fd_count; i++)
301 fd = wfds->fd_array[i];
302 h = (HANDLE) _get_osfhandle (fd);
303 if (IsConsoleHandle (h)
304 && GetNumberOfConsoleInputEvents (h, &nbuffer))
307 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
308 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
311 wfds = (fd_set *) alloca (sizeof (fd_set));
314 for (i = 0; i < xfds->fd_count; i++)
316 fd = xfds->fd_array[i];
317 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
318 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
321 xfds = (fd_set *) alloca (sizeof (fd_set));
323 /* Zero all the fd_sets, including the application's. */
327 FD_ZERO (&handle_rfds);
328 FD_ZERO (&handle_wfds);
329 FD_ZERO (&handle_xfds);
331 /* Classify handles. Create fd sets for sockets, poll the others. */
332 for (i = 0; i < nfds; i++)
334 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
337 h = (HANDLE) _get_osfhandle (i);
344 if (IsSocketHandle (h))
346 int requested = FD_CLOSE;
348 /* See above; socket handles are mapped onto select, but we
349 need to map descriptors to handles. */
350 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
352 requested |= FD_READ | FD_ACCEPT;
353 FD_SET ((SOCKET) h, rfds);
354 FD_SET ((SOCKET) h, &handle_rfds);
356 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
358 requested |= FD_WRITE | FD_CONNECT;
359 FD_SET ((SOCKET) h, wfds);
360 FD_SET ((SOCKET) h, &handle_wfds);
362 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
365 FD_SET ((SOCKET) h, xfds);
366 FD_SET ((SOCKET) h, &handle_xfds);
369 WSAEventSelect ((SOCKET) h, hEvent, requested);
374 handle_array[nhandles++] = h;
376 /* Poll now. If we get an event, do not wait below. */
377 if (wait_timeout != 0
378 && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
383 if (wait_timeout == 0 || nsock == 0)
387 /* See if we need to wait in the loop below. If any select is ready,
388 do MsgWaitForMultipleObjects anyway to dispatch messages, but
389 no need to call select again. */
390 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
393 /* Restore the fd_sets for the other select we do below. */
394 memcpy (&handle_rfds, rfds, sizeof (fd_set));
395 memcpy (&handle_wfds, wfds, sizeof (fd_set));
396 memcpy (&handle_xfds, xfds, sizeof (fd_set));
404 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
405 wait_timeout, QS_ALLINPUT);
407 if (ret == WAIT_OBJECT_0 + nhandles)
409 /* new input of some other kind */
411 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
413 TranslateMessage (&msg);
414 DispatchMessage (&msg);
421 /* If we haven't done it yet, check the status of the sockets. */
422 if (rc == 0 && nsock > 0)
423 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
425 /* Now fill in the results. */
430 /* Place a sentinel at the end of the array. */
431 handle_array[nhandles] = NULL;
433 for (i = 0; i < nfds; i++)
435 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
438 h = (HANDLE) _get_osfhandle (i);
439 if (h != handle_array[nhandles])
441 /* Perform handle->descriptor mapping. Don't update rc, as these
442 results are counted in the return value of Winsock's select. */
443 WSAEventSelect ((SOCKET) h, NULL, 0);
444 if (FD_ISSET (h, &handle_rfds))
446 if (FD_ISSET (h, &handle_wfds))
448 if (FD_ISSET (h, &handle_xfds))
455 windows_poll_handle (h, i, &rbits, &wbits, &xbits);
456 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
461 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
466 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
477 #else /* ! Native Windows. */
479 #include <sys/select.h>
484 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
485 struct timeval *timeout)
487 /* Interix 3.5 has a bug: it does not support nfds == 0. */
495 return select (nfds, rfds, wfds, xfds, timeout);