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 /* Get the overridden 'struct timeval'. */
43 #include "msvc-nothrow.h"
48 unsigned char in[FD_SETSIZE / CHAR_BIT];
49 unsigned char out[FD_SETSIZE / CHAR_BIT];
52 /* Declare data structures for ntdll functions. */
53 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
55 ULONG NamedPipeConfiguration;
56 ULONG MaximumInstances;
57 ULONG CurrentInstances;
59 ULONG ReadDataAvailable;
61 ULONG WriteQuotaAvailable;
64 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
66 typedef struct _IO_STATUS_BLOCK
72 ULONG_PTR Information;
73 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
75 typedef enum _FILE_INFORMATION_CLASS {
76 FilePipeLocalInformation = 24
77 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
79 typedef DWORD (WINAPI *PNtQueryInformationFile)
80 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
86 /* Optimized test whether a HANDLE refers to a console.
87 See <http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00065.html>. */
88 #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3)
91 IsSocketHandle (HANDLE h)
95 if (IsConsoleHandle (h))
98 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
99 WSAEnumNetworkEvents instead distinguishes the two correctly. */
100 ev.lNetworkEvents = 0xDEADBEEF;
101 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
102 return ev.lNetworkEvents != 0xDEADBEEF;
105 /* Compute output fd_sets for libc descriptor FD (whose Windows handle is
109 windows_poll_handle (HANDLE h, int fd,
110 struct bitset *rbits,
111 struct bitset *wbits,
112 struct bitset *xbits)
114 BOOL read, write, except;
116 INPUT_RECORD *irbuffer;
117 DWORD avail, nbuffer;
119 IO_STATUS_BLOCK iosb;
120 FILE_PIPE_LOCAL_INFORMATION fpli;
121 static PNtQueryInformationFile NtQueryInformationFile;
122 static BOOL once_only;
124 read = write = except = FALSE;
125 switch (GetFileType (h))
135 NtQueryInformationFile = (PNtQueryInformationFile)
136 GetProcAddress (GetModuleHandle ("ntdll.dll"),
137 "NtQueryInformationFile");
141 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
146 else if (GetLastError () == ERROR_BROKEN_PIPE)
151 /* It was the write-end of the pipe. Check if it is writable.
152 If NtQueryInformationFile fails, optimistically assume the pipe is
153 writable. This could happen on Windows 9x, where
154 NtQueryInformationFile is not available, or if we inherit a pipe
155 that doesn't permit FILE_READ_ATTRIBUTES access on the write end
156 (I think this should not happen since Windows XP SP2; WINE seems
157 fine too). Otherwise, ensure that enough space is available for
159 memset (&iosb, 0, sizeof (iosb));
160 memset (&fpli, 0, sizeof (fpli));
162 if (!NtQueryInformationFile
163 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
164 FilePipeLocalInformation)
165 || fpli.WriteQuotaAvailable >= PIPE_BUF
166 || (fpli.OutboundQuota < PIPE_BUF &&
167 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
174 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
177 ret = WaitForSingleObject (h, 0);
178 if (ret == WAIT_OBJECT_0)
180 if (!IsConsoleHandle (h))
187 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
189 /* Screen buffers handles are filtered earlier. */
197 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
198 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
199 if (!bRet || avail == 0)
205 for (i = 0; i < avail; i++)
206 if (irbuffer[i].EventType == KEY_EVENT)
212 ret = WaitForSingleObject (h, 0);
214 if (ret == WAIT_OBJECT_0)
221 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
223 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
227 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
229 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
233 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
235 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
243 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
244 struct timeval *timeout)
247 static struct timeval tv0;
248 static HANDLE hEvent;
249 HANDLE h, handle_array[FD_SETSIZE + 2];
250 fd_set handle_rfds, handle_wfds, handle_xfds;
251 struct bitset rbits, wbits, xbits;
252 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
253 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
257 if (nfds > FD_SETSIZE)
261 wait_timeout = INFINITE;
264 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
266 /* select is also used as a portable usleep. */
267 if (!rfds && !wfds && !xfds)
269 Sleep (wait_timeout);
275 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
277 handle_array[0] = hEvent;
281 /* Copy descriptors to bitsets. At the same time, eliminate
282 bits in the "wrong" direction for console input buffers
283 and screen buffers, because screen buffers are waitable
284 and they will block until a character is available. */
285 memset (&rbits, 0, sizeof (rbits));
286 memset (&wbits, 0, sizeof (wbits));
287 memset (&xbits, 0, sizeof (xbits));
288 memset (anyfds_in, 0, sizeof (anyfds_in));
290 for (i = 0; i < rfds->fd_count; i++)
292 fd = rfds->fd_array[i];
293 h = (HANDLE) _get_osfhandle (fd);
294 if (IsConsoleHandle (h)
295 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
298 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
299 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
302 rfds = (fd_set *) alloca (sizeof (fd_set));
305 for (i = 0; i < wfds->fd_count; i++)
307 fd = wfds->fd_array[i];
308 h = (HANDLE) _get_osfhandle (fd);
309 if (IsConsoleHandle (h)
310 && GetNumberOfConsoleInputEvents (h, &nbuffer))
313 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
314 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
317 wfds = (fd_set *) alloca (sizeof (fd_set));
320 for (i = 0; i < xfds->fd_count; i++)
322 fd = xfds->fd_array[i];
323 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
324 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
327 xfds = (fd_set *) alloca (sizeof (fd_set));
329 /* Zero all the fd_sets, including the application's. */
333 FD_ZERO (&handle_rfds);
334 FD_ZERO (&handle_wfds);
335 FD_ZERO (&handle_xfds);
337 /* Classify handles. Create fd sets for sockets, poll the others. */
338 for (i = 0; i < nfds; i++)
340 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
343 h = (HANDLE) _get_osfhandle (i);
350 if (IsSocketHandle (h))
352 int requested = FD_CLOSE;
354 /* See above; socket handles are mapped onto select, but we
355 need to map descriptors to handles. */
356 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
358 requested |= FD_READ | FD_ACCEPT;
359 FD_SET ((SOCKET) h, rfds);
360 FD_SET ((SOCKET) h, &handle_rfds);
362 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
364 requested |= FD_WRITE | FD_CONNECT;
365 FD_SET ((SOCKET) h, wfds);
366 FD_SET ((SOCKET) h, &handle_wfds);
368 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
371 FD_SET ((SOCKET) h, xfds);
372 FD_SET ((SOCKET) h, &handle_xfds);
375 WSAEventSelect ((SOCKET) h, hEvent, requested);
380 handle_array[nhandles++] = h;
382 /* Poll now. If we get an event, do not wait below. */
383 if (wait_timeout != 0
384 && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
389 if (wait_timeout == 0 || nsock == 0)
393 /* See if we need to wait in the loop below. If any select is ready,
394 do MsgWaitForMultipleObjects anyway to dispatch messages, but
395 no need to call select again. */
396 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
399 /* Restore the fd_sets for the other select we do below. */
400 memcpy (&handle_rfds, rfds, sizeof (fd_set));
401 memcpy (&handle_wfds, wfds, sizeof (fd_set));
402 memcpy (&handle_xfds, xfds, sizeof (fd_set));
410 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
411 wait_timeout, QS_ALLINPUT);
413 if (ret == WAIT_OBJECT_0 + nhandles)
415 /* new input of some other kind */
417 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
419 TranslateMessage (&msg);
420 DispatchMessage (&msg);
427 /* If we haven't done it yet, check the status of the sockets. */
428 if (rc == 0 && nsock > 0)
429 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
431 /* Now fill in the results. */
436 /* Place a sentinel at the end of the array. */
437 handle_array[nhandles] = NULL;
439 for (i = 0; i < nfds; i++)
441 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
444 h = (HANDLE) _get_osfhandle (i);
445 if (h != handle_array[nhandles])
447 /* Perform handle->descriptor mapping. Don't update rc, as these
448 results are counted in the return value of Winsock's select. */
449 WSAEventSelect ((SOCKET) h, NULL, 0);
450 if (FD_ISSET (h, &handle_rfds))
452 if (FD_ISSET (h, &handle_wfds))
454 if (FD_ISSET (h, &handle_xfds))
461 windows_poll_handle (h, i, &rbits, &wbits, &xbits);
462 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
467 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
472 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
483 #else /* ! Native Windows. */
485 #include <sys/select.h>
490 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
491 struct timeval *timeout)
493 /* Interix 3.5 has a bug: it does not support nfds == 0. */
501 return select (nfds, rfds, wfds, xfds, timeout);