1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2011 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 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
84 IsSocketHandle (HANDLE h)
88 if (IsConsoleHandle (h))
91 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
92 WSAEnumNetworkEvents instead distinguishes the two correctly. */
93 ev.lNetworkEvents = 0xDEADBEEF;
94 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
95 return ev.lNetworkEvents != 0xDEADBEEF;
98 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
101 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
102 struct bitset *xbits)
104 BOOL read, write, except;
106 INPUT_RECORD *irbuffer;
107 DWORD avail, nbuffer;
109 IO_STATUS_BLOCK iosb;
110 FILE_PIPE_LOCAL_INFORMATION fpli;
111 static PNtQueryInformationFile NtQueryInformationFile;
112 static BOOL once_only;
114 read = write = except = FALSE;
115 switch (GetFileType (h))
125 NtQueryInformationFile = (PNtQueryInformationFile)
126 GetProcAddress (GetModuleHandle ("ntdll.dll"),
127 "NtQueryInformationFile");
131 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
136 else if (GetLastError () == ERROR_BROKEN_PIPE)
141 /* It was the write-end of the pipe. Check if it is writable.
142 If NtQueryInformationFile fails, optimistically assume the pipe is
143 writable. This could happen on Win9x, where NtQueryInformationFile
144 is not available, or if we inherit a pipe that doesn't permit
145 FILE_READ_ATTRIBUTES access on the write end (I think this should
146 not happen since WinXP SP2; WINE seems fine too). Otherwise,
147 ensure that enough space is available for atomic writes. */
148 memset (&iosb, 0, sizeof (iosb));
149 memset (&fpli, 0, sizeof (fpli));
151 if (!NtQueryInformationFile
152 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
153 FilePipeLocalInformation)
154 || fpli.WriteQuotaAvailable >= PIPE_BUF
155 || (fpli.OutboundQuota < PIPE_BUF &&
156 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
163 if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
166 ret = WaitForSingleObject (h, 0);
167 if (ret == WAIT_OBJECT_0)
169 if (!IsConsoleHandle (h))
176 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
178 /* Screen buffers handles are filtered earlier. */
186 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
187 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
188 if (!bRet || avail == 0)
194 for (i = 0; i < avail; i++)
195 if (irbuffer[i].EventType == KEY_EVENT)
201 ret = WaitForSingleObject (h, 0);
203 if (ret == WAIT_OBJECT_0)
210 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
212 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
216 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
218 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
222 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
224 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
232 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
233 struct timeval *timeout)
235 static struct timeval tv0;
236 static HANDLE hEvent;
237 HANDLE h, handle_array[FD_SETSIZE + 2];
238 fd_set handle_rfds, handle_wfds, handle_xfds;
239 struct bitset rbits, wbits, xbits;
240 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
241 DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
245 if (nfds > FD_SETSIZE)
249 wait_timeout = INFINITE;
252 wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
254 /* select is also used as a portable usleep. */
255 if (!rfds && !wfds && !xfds)
257 Sleep (wait_timeout);
263 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
265 handle_array[0] = hEvent;
269 /* Copy descriptors to bitsets. At the same time, eliminate
270 bits in the "wrong" direction for console input buffers
271 and screen buffers, because screen buffers are waitable
272 and they will block until a character is available. */
273 memset (&rbits, 0, sizeof (rbits));
274 memset (&wbits, 0, sizeof (wbits));
275 memset (&xbits, 0, sizeof (xbits));
276 memset (anyfds_in, 0, sizeof (anyfds_in));
278 for (i = 0; i < rfds->fd_count; i++)
280 fd = rfds->fd_array[i];
281 h = (HANDLE) _get_osfhandle (fd);
282 if (IsConsoleHandle (h)
283 && !GetNumberOfConsoleInputEvents (h, &nbuffer))
286 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
287 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
290 rfds = (fd_set *) alloca (sizeof (fd_set));
293 for (i = 0; i < wfds->fd_count; i++)
295 fd = wfds->fd_array[i];
296 h = (HANDLE) _get_osfhandle (fd);
297 if (IsConsoleHandle (h)
298 && GetNumberOfConsoleInputEvents (h, &nbuffer))
301 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
302 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
305 wfds = (fd_set *) alloca (sizeof (fd_set));
308 for (i = 0; i < xfds->fd_count; i++)
310 fd = xfds->fd_array[i];
311 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
312 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
315 xfds = (fd_set *) alloca (sizeof (fd_set));
317 /* Zero all the fd_sets, including the application's. */
321 FD_ZERO (&handle_rfds);
322 FD_ZERO (&handle_wfds);
323 FD_ZERO (&handle_xfds);
325 /* Classify handles. Create fd sets for sockets, poll the others. */
326 for (i = 0; i < nfds; i++)
328 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
331 h = (HANDLE) _get_osfhandle (i);
338 if (IsSocketHandle (h))
340 int requested = FD_CLOSE;
342 /* See above; socket handles are mapped onto select, but we
343 need to map descriptors to handles. */
344 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
346 requested |= FD_READ | FD_ACCEPT;
347 FD_SET ((SOCKET) h, rfds);
348 FD_SET ((SOCKET) h, &handle_rfds);
350 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
352 requested |= FD_WRITE | FD_CONNECT;
353 FD_SET ((SOCKET) h, wfds);
354 FD_SET ((SOCKET) h, &handle_wfds);
356 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
359 FD_SET ((SOCKET) h, xfds);
360 FD_SET ((SOCKET) h, &handle_xfds);
363 WSAEventSelect ((SOCKET) h, hEvent, requested);
368 handle_array[nhandles++] = h;
370 /* Poll now. If we get an event, do not wait below. */
371 if (wait_timeout != 0
372 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
377 if (wait_timeout == 0 || nsock == 0)
381 /* See if we need to wait in the loop below. If any select is ready,
382 do MsgWaitForMultipleObjects anyway to dispatch messages, but
383 no need to call select again. */
384 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
387 /* Restore the fd_sets for the other select we do below. */
388 memcpy (&handle_rfds, rfds, sizeof (fd_set));
389 memcpy (&handle_wfds, wfds, sizeof (fd_set));
390 memcpy (&handle_xfds, xfds, sizeof (fd_set));
398 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
399 wait_timeout, QS_ALLINPUT);
401 if (ret == WAIT_OBJECT_0 + nhandles)
403 /* new input of some other kind */
405 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
407 TranslateMessage (&msg);
408 DispatchMessage (&msg);
415 /* If we haven't done it yet, check the status of the sockets. */
416 if (rc == 0 && nsock > 0)
417 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
419 /* Now fill in the results. */
424 /* Place a sentinel at the end of the array. */
425 handle_array[nhandles] = NULL;
427 for (i = 0; i < nfds; i++)
429 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
432 h = (HANDLE) _get_osfhandle (i);
433 if (h != handle_array[nhandles])
435 /* Perform handle->descriptor mapping. Don't update rc, as these
436 results are counted in the return value of Winsock's select. */
437 WSAEventSelect ((SOCKET) h, NULL, 0);
438 if (FD_ISSET (h, &handle_rfds))
440 if (FD_ISSET (h, &handle_wfds))
442 if (FD_ISSET (h, &handle_xfds))
449 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
450 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
455 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
460 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
471 #else /* ! Native Win32. */
473 #include <sys/select.h>
478 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
479 struct timeval *timeout)
481 /* Interix 3.5 has a bug: it does not support nfds == 0. */
489 return select (nfds, rfds, wfds, xfds, timeout);