1 /* Emulation for select(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2008-2009 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. */
25 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
28 #include <sys/types.h>
41 unsigned char in[FD_SETSIZE / CHAR_BIT];
42 unsigned char out[FD_SETSIZE / CHAR_BIT];
45 /* Declare data structures for ntdll functions. */
46 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
48 ULONG NamedPipeConfiguration;
49 ULONG MaximumInstances;
50 ULONG CurrentInstances;
52 ULONG ReadDataAvailable;
54 ULONG WriteQuotaAvailable;
57 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
59 typedef struct _IO_STATUS_BLOCK
65 ULONG_PTR Information;
66 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
68 typedef enum _FILE_INFORMATION_CLASS {
69 FilePipeLocalInformation = 24
70 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
72 typedef DWORD (WINAPI *PNtQueryInformationFile)
73 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
79 /* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H). */
82 win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
85 BOOL read, write, except;
87 INPUT_RECORD *irbuffer;
91 FILE_PIPE_LOCAL_INFORMATION fpli;
92 static PNtQueryInformationFile NtQueryInformationFile;
93 static BOOL once_only;
95 read = write = except = FALSE;
96 switch (GetFileType (h))
106 NtQueryInformationFile = (PNtQueryInformationFile)
107 GetProcAddress (GetModuleHandle ("ntdll.dll"),
108 "NtQueryInformationFile");
112 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
120 /* It was the write-end of the pipe. Check if it is writable.
121 If NtQueryInformationFile fails, optimistically assume the pipe is
122 writable. This could happen on Win9x, where NtQueryInformationFile
123 is not available, or if we inherit a pipe that doesn't permit
124 FILE_READ_ATTRIBUTES access on the write end (I think this should
125 not happen since WinXP SP2; WINE seems fine too). Otherwise,
126 ensure that enough space is available for atomic writes. */
127 memset (&iosb, 0, sizeof (iosb));
128 memset (&fpli, 0, sizeof (fpli));
130 if (!NtQueryInformationFile
131 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
132 FilePipeLocalInformation)
133 || fpli.WriteQuotaAvailable >= PIPE_BUF
134 || (fpli.OutboundQuota < PIPE_BUF &&
135 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
141 ret = WaitForSingleObject (h, 0);
143 if (ret == WAIT_OBJECT_0)
146 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
147 if (!bRet || nbuffer == 0)
150 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
151 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
152 if (!bRet || avail == 0)
155 for (i = 0; i < avail; i++)
156 if (irbuffer[i].EventType == KEY_EVENT)
162 ret = WaitForSingleObject (h, 0);
164 if (ret == WAIT_OBJECT_0)
171 if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
173 rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
177 if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
179 wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
183 if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
185 xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
193 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
194 struct timeval *timeout)
196 static struct timeval tv0;
197 static HANDLE hEvent;
198 HANDLE h, handle_array[FD_SETSIZE + 2];
199 fd_set handle_rfds, handle_wfds, handle_xfds;
200 struct bitset rbits, wbits, xbits;
201 unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
202 DWORD ret, wait_timeout, nhandles, nsock;
206 if (nfds > FD_SETSIZE)
210 wait_timeout = INFINITE;
213 wait_timeout = timeout->tv_sec + timeout->tv_usec / 1000;
215 /* select is also used as a portable usleep. */
216 if (!rfds && !wfds && !xfds)
218 Sleep (wait_timeout);
224 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
226 handle_array[0] = hEvent;
230 /* Copy descriptors to bitsets. */
231 memset (&rbits, 0, sizeof (rbits));
232 memset (&wbits, 0, sizeof (wbits));
233 memset (&xbits, 0, sizeof (xbits));
234 memset (anyfds_in, 0, sizeof (anyfds_in));
236 for (i = 0; i < rfds->fd_count; i++)
238 fd = rfds->fd_array[i];
239 rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
240 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
243 rfds = (fd_set *) alloca (sizeof (fd_set));
246 for (i = 0; i < wfds->fd_count; i++)
248 fd = wfds->fd_array[i];
249 wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
250 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
253 wfds = (fd_set *) alloca (sizeof (fd_set));
256 for (i = 0; i < xfds->fd_count; i++)
258 fd = xfds->fd_array[i];
259 xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
260 anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
263 xfds = (fd_set *) alloca (sizeof (fd_set));
265 /* Zero all the fd_sets, including the application's. */
269 FD_ZERO (&handle_rfds);
270 FD_ZERO (&handle_wfds);
271 FD_ZERO (&handle_xfds);
273 /* Classify handles. Create fd sets for sockets, poll the others. */
274 for (i = 0; i < nfds; i++)
278 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
281 h = (HANDLE) _get_osfhandle (i);
288 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
289 WSAEnumNetworkEvents instead distinguishes the two correctly. */
290 ev.lNetworkEvents = 0xDEADBEEF;
291 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
292 if (ev.lNetworkEvents != 0xDEADBEEF)
294 int requested = FD_CLOSE;
296 /* See above; socket handles are mapped onto select, but we
297 need to map descriptors to handles. */
298 if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
300 requested |= FD_READ | FD_ACCEPT;
301 FD_SET ((SOCKET) h, rfds);
302 FD_SET ((SOCKET) h, &handle_rfds);
304 if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
306 requested |= FD_WRITE | FD_CONNECT;
307 FD_SET ((SOCKET) h, wfds);
308 FD_SET ((SOCKET) h, &handle_wfds);
310 if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
313 FD_SET ((SOCKET) h, xfds);
314 FD_SET ((SOCKET) h, &handle_xfds);
317 WSAEventSelect ((SOCKET) h, hEvent, requested);
322 handle_array[nhandles++] = h;
324 /* Poll now. If we get an event, do not wait below. */
325 if (wait_timeout != 0
326 && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
331 if (wait_timeout == 0 || nsock == 0)
335 /* See if we need to wait in the loop below. If any select is ready,
336 do MsgWaitForMultipleObjects anyway to dispatch messages, but
337 no need to call select again. */
338 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
341 /* Restore the fd_sets for the other select we do below. */
342 memcpy (&handle_rfds, rfds, sizeof (fd_set));
343 memcpy (&handle_wfds, wfds, sizeof (fd_set));
344 memcpy (&handle_xfds, xfds, sizeof (fd_set));
352 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
353 wait_timeout, QS_ALLINPUT);
355 if (ret == WAIT_OBJECT_0 + nhandles)
357 /* new input of some other kind */
359 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
361 TranslateMessage (&msg);
362 DispatchMessage (&msg);
369 /* If we haven't done it yet, check the status of the sockets. */
370 if (rc == 0 && nsock > 0)
371 rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
373 /* Now fill in the results. */
378 /* Place a sentinel at the end of the array. */
379 handle_array[nhandles] = NULL;
381 for (i = 0; i < nfds; i++)
383 if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
386 h = (HANDLE) _get_osfhandle (i);
387 if (h != handle_array[nhandles])
389 /* Perform handle->descriptor mapping. Don't update rc, as these
390 results are counted in the return value of Winsock's select. */
391 WSAEventSelect ((SOCKET) h, NULL, 0);
392 if (FD_ISSET (h, &handle_rfds))
394 if (FD_ISSET (h, &handle_wfds))
396 if (FD_ISSET (h, &handle_xfds))
403 win32_poll_handle (h, i, &rbits, &wbits, &xbits);
404 if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
409 if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
414 if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
425 #else /* ! Native Win32. */
427 #include <sys/select.h>
432 rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
433 struct timeval *timeout)
435 /* Interix 3.5 has a bug: it does not support nfds == 0. */
443 return select (nfds, rfds, wfds, xfds, timeout);