1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-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. */
22 /* Tell gcc not to warn about the (nfd < 0) tests, below. */
23 #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
24 # pragma GCC diagnostic ignored "-Wtype-limits"
30 #include <sys/types.h>
36 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
38 # include <winsock2.h>
44 # include <sys/time.h>
45 # include <sys/socket.h>
46 # include <sys/select.h>
50 #ifdef HAVE_SYS_IOCTL_H
51 # include <sys/ioctl.h>
53 #ifdef HAVE_SYS_FILIO_H
54 # include <sys/filio.h>
63 /* BeOS does not have MSG_PEEK. */
70 /* Declare data structures for ntdll functions. */
71 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
73 ULONG NamedPipeConfiguration;
74 ULONG MaximumInstances;
75 ULONG CurrentInstances;
77 ULONG ReadDataAvailable;
79 ULONG WriteQuotaAvailable;
82 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
84 typedef struct _IO_STATUS_BLOCK
90 ULONG_PTR Information;
91 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
93 typedef enum _FILE_INFORMATION_CLASS {
94 FilePipeLocalInformation = 24
95 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
97 typedef DWORD (WINAPI *PNtQueryInformationFile)
98 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
101 # define PIPE_BUF 512
104 /* Compute revents values for file handle H. */
107 win32_compute_revents (HANDLE h, int sought)
109 int i, ret, happened;
110 INPUT_RECORD *irbuffer;
111 DWORD avail, nbuffer;
113 IO_STATUS_BLOCK iosb;
114 FILE_PIPE_LOCAL_INFORMATION fpli;
115 static PNtQueryInformationFile NtQueryInformationFile;
116 static BOOL once_only;
118 switch (GetFileType (h))
123 NtQueryInformationFile = (PNtQueryInformationFile)
124 GetProcAddress (GetModuleHandle ("ntdll.dll"),
125 "NtQueryInformationFile");
130 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
133 happened |= sought & (POLLIN | POLLRDNORM);
138 /* It was the write-end of the pipe. Check if it is writable.
139 If NtQueryInformationFile fails, optimistically assume the pipe is
140 writable. This could happen on Win9x, where NtQueryInformationFile
141 is not available, or if we inherit a pipe that doesn't permit
142 FILE_READ_ATTRIBUTES access on the write end (I think this should
143 not happen since WinXP SP2; WINE seems fine too). Otherwise,
144 ensure that enough space is available for atomic writes. */
145 memset (&iosb, 0, sizeof (iosb));
146 memset (&fpli, 0, sizeof (fpli));
148 if (!NtQueryInformationFile
149 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
150 FilePipeLocalInformation)
151 || fpli.WriteQuotaAvailable >= PIPE_BUF
152 || (fpli.OutboundQuota < PIPE_BUF &&
153 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
154 happened |= sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
159 ret = WaitForSingleObject (h, 0);
160 if (ret == WAIT_OBJECT_0)
163 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
164 if (!bRet || nbuffer == 0)
167 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
168 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
169 if (!bRet || avail == 0)
172 for (i = 0; i < avail; i++)
173 if (irbuffer[i].EventType == KEY_EVENT)
174 return sought & ~(POLLPRI | POLLRDBAND);
179 ret = WaitForSingleObject (h, 0);
180 if (ret == WAIT_OBJECT_0)
181 return sought & ~(POLLPRI | POLLRDBAND);
186 return sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
189 /* Convert fd_sets returned by select into revents values. */
192 win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
196 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
197 happened |= (POLLIN | POLLRDNORM) & sought;
199 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
205 r = recv (h, data, sizeof (data), MSG_PEEK);
206 error = WSAGetLastError ();
209 if (r > 0 || error == WSAENOTCONN)
210 happened |= (POLLIN | POLLRDNORM) & sought;
212 /* Distinguish hung-up sockets from other errors. */
213 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
214 || error == WSAECONNABORTED || error == WSAENETRESET)
221 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
222 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
224 if (lNetworkEvents & FD_OOB)
225 happened |= (POLLPRI | POLLRDBAND) & sought;
232 /* Convert select(2) returned fd_sets into poll(2) revents values. */
234 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
237 if (FD_ISSET (fd, rfds))
242 # if defined __MACH__ && defined __APPLE__
243 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
244 for some kinds of descriptors. Detect if this descriptor is a
245 connected socket, a server socket, or something else using a
246 0-byte recv, and use ioctl(2) to detect POLLHUP. */
247 r = recv (fd, NULL, 0, MSG_PEEK);
248 socket_errno = (r < 0) ? errno : 0;
249 if (r == 0 || socket_errno == ENOTSOCK)
250 ioctl (fd, FIONREAD, &r);
253 r = recv (fd, data, sizeof (data), MSG_PEEK);
254 socket_errno = (r < 0) ? errno : 0;
259 /* If the event happened on an unconnected server socket,
261 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
262 happened |= (POLLIN | POLLRDNORM) & sought;
264 /* Distinguish hung-up sockets from other errors. */
265 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
266 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
273 if (FD_ISSET (fd, wfds))
274 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
276 if (FD_ISSET (fd, efds))
277 happened |= (POLLPRI | POLLRDBAND) & sought;
284 poll (pfd, nfd, timeout)
290 fd_set rfds, wfds, efds;
297 static int sc_open_max = -1;
300 || (nfd > sc_open_max
301 && (sc_open_max != -1
302 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
307 # else /* !_SC_OPEN_MAX */
309 if (nfd < 0 || nfd > OPEN_MAX)
314 # endif /* OPEN_MAX -- else, no check is needed */
315 # endif /* !_SC_OPEN_MAX */
317 /* EFAULT is not necessary to implement, but let's do it in the
325 /* convert timeout number into a timeval structure */
332 else if (timeout > 0)
335 ptv->tv_sec = timeout / 1000;
336 ptv->tv_usec = (timeout % 1000) * 1000;
338 else if (timeout == INFTIM)
347 /* create fd sets and determine max fd */
352 for (i = 0; i < nfd; i++)
357 if (pfd[i].events & (POLLIN | POLLRDNORM))
358 FD_SET (pfd[i].fd, &rfds);
360 /* see select(2): "the only exceptional condition detectable
361 is out-of-band data received on a socket", hence we push
362 POLLWRBAND events onto wfds instead of efds. */
363 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
364 FD_SET (pfd[i].fd, &wfds);
365 if (pfd[i].events & (POLLPRI | POLLRDBAND))
366 FD_SET (pfd[i].fd, &efds);
367 if (pfd[i].fd >= maxfd
368 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
369 | POLLRDNORM | POLLRDBAND
370 | POLLWRNORM | POLLWRBAND)))
373 if (maxfd > FD_SETSIZE)
381 /* examine fd sets */
382 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
386 /* establish results */
388 for (i = 0; i < nfd; i++)
393 int happened = compute_revents (pfd[i].fd, pfd[i].events,
394 &rfds, &wfds, &efds);
397 pfd[i].revents = happened;
404 static struct timeval tv0;
405 static HANDLE hEvent;
407 HANDLE h, handle_array[FD_SETSIZE + 2];
408 DWORD ret, wait_timeout, nhandles;
409 fd_set rfds, wfds, xfds;
415 if (nfd < 0 || timeout < -1)
422 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
424 handle_array[0] = hEvent;
430 /* Classify socket handles and create fd sets. */
431 for (i = 0; i < nfd; i++)
436 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
437 POLLOUT | POLLWRNORM | POLLWRBAND)))
440 h = (HANDLE) _get_osfhandle (pfd[i].fd);
443 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
444 WSAEnumNetworkEvents instead distinguishes the two correctly. */
445 ev.lNetworkEvents = 0xDEADBEEF;
446 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
447 if (ev.lNetworkEvents != 0xDEADBEEF)
449 int requested = FD_CLOSE;
451 /* see above; socket handles are mapped onto select. */
452 if (pfd[i].events & (POLLIN | POLLRDNORM))
454 requested |= FD_READ | FD_ACCEPT;
455 FD_SET ((SOCKET) h, &rfds);
457 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
459 requested |= FD_WRITE | FD_CONNECT;
460 FD_SET ((SOCKET) h, &wfds);
462 if (pfd[i].events & (POLLPRI | POLLRDBAND))
465 FD_SET ((SOCKET) h, &xfds);
469 WSAEventSelect ((SOCKET) h, hEvent, requested);
473 handle_array[nhandles++] = h;
475 /* Poll now. If we get an event, do not poll again. */
476 pfd[i].revents = win32_compute_revents (h, pfd[i].events);
482 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
484 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
485 no need to call select again. */
492 if (timeout == INFTIM)
493 wait_timeout = INFINITE;
495 wait_timeout = timeout;
500 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
501 wait_timeout, QS_ALLINPUT);
503 if (ret == WAIT_OBJECT_0 + nhandles)
505 /* new input of some other kind */
507 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
509 TranslateMessage (&msg);
510 DispatchMessage (&msg);
518 select (0, &rfds, &wfds, &xfds, &tv0);
520 /* Place a sentinel at the end of the array. */
521 handle_array[nhandles] = NULL;
523 for (i = 0; i < nfd; i++)
529 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
530 POLLOUT | POLLWRNORM | POLLWRBAND)))
533 h = (HANDLE) _get_osfhandle (pfd[i].fd);
534 if (h != handle_array[nhandles])
537 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
538 WSAEventSelect ((SOCKET) h, 0, 0);
540 /* If we're lucky, WSAEnumNetworkEvents already provided a way
541 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
542 if (FD_ISSET ((SOCKET) h, &rfds)
543 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
544 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
545 if (FD_ISSET ((SOCKET) h, &wfds))
546 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
547 if (FD_ISSET ((SOCKET) h, &xfds))
548 ev.lNetworkEvents |= FD_OOB;
550 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
557 happened = win32_compute_revents (h, pfd[i].events);
560 if ((pfd[i].revents |= happened) != 0)