mingw: import poll-emulation from gnulib
[git/dscho.git] / compat / win32 / sys / poll.c
blob092d05e6bd617a7b27afb777783f892ba78cfefd
1 /* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
4 Copyright 2001-2003, 2006-2010 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)
11 any later version.
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"
25 #endif
27 #include <config.h>
28 #include <alloca.h>
30 #include <sys/types.h>
31 #include "poll.h"
32 #include <errno.h>
33 #include <limits.h>
34 #include <assert.h>
36 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
37 # define WIN32_NATIVE
38 # include <winsock2.h>
39 # include <windows.h>
40 # include <io.h>
41 # include <stdio.h>
42 # include <conio.h>
43 #else
44 # include <sys/time.h>
45 # include <sys/socket.h>
46 # include <sys/select.h>
47 # include <unistd.h>
48 #endif
50 #ifdef HAVE_SYS_IOCTL_H
51 # include <sys/ioctl.h>
52 #endif
53 #ifdef HAVE_SYS_FILIO_H
54 # include <sys/filio.h>
55 #endif
57 #include <time.h>
59 #ifndef INFTIM
60 # define INFTIM (-1)
61 #endif
63 /* BeOS does not have MSG_PEEK. */
64 #ifndef MSG_PEEK
65 # define MSG_PEEK 0
66 #endif
68 #ifdef WIN32_NATIVE
70 #define IsConsoleHandle(h) (((long) (h) & 3) == 3)
72 static BOOL
73 IsSocketHandle (HANDLE h)
75 WSANETWORKEVENTS ev;
77 if (IsConsoleHandle (h))
78 return FALSE;
80 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
81 WSAEnumNetworkEvents instead distinguishes the two correctly. */
82 ev.lNetworkEvents = 0xDEADBEEF;
83 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
84 return ev.lNetworkEvents != 0xDEADBEEF;
87 /* Declare data structures for ntdll functions. */
88 typedef struct _FILE_PIPE_LOCAL_INFORMATION {
89 ULONG NamedPipeType;
90 ULONG NamedPipeConfiguration;
91 ULONG MaximumInstances;
92 ULONG CurrentInstances;
93 ULONG InboundQuota;
94 ULONG ReadDataAvailable;
95 ULONG OutboundQuota;
96 ULONG WriteQuotaAvailable;
97 ULONG NamedPipeState;
98 ULONG NamedPipeEnd;
99 } FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
101 typedef struct _IO_STATUS_BLOCK
103 union {
104 DWORD Status;
105 PVOID Pointer;
106 } u;
107 ULONG_PTR Information;
108 } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
110 typedef enum _FILE_INFORMATION_CLASS {
111 FilePipeLocalInformation = 24
112 } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
114 typedef DWORD (WINAPI *PNtQueryInformationFile)
115 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
117 # ifndef PIPE_BUF
118 # define PIPE_BUF 512
119 # endif
121 /* Compute revents values for file handle H. If some events cannot happen
122 for the handle, eliminate them from *P_SOUGHT. */
124 static int
125 win32_compute_revents (HANDLE h, int *p_sought)
127 int i, ret, happened;
128 INPUT_RECORD *irbuffer;
129 DWORD avail, nbuffer;
130 BOOL bRet;
131 IO_STATUS_BLOCK iosb;
132 FILE_PIPE_LOCAL_INFORMATION fpli;
133 static PNtQueryInformationFile NtQueryInformationFile;
134 static BOOL once_only;
136 switch (GetFileType (h))
138 case FILE_TYPE_PIPE:
139 if (!once_only)
141 NtQueryInformationFile = (PNtQueryInformationFile)
142 GetProcAddress (GetModuleHandle ("ntdll.dll"),
143 "NtQueryInformationFile");
144 once_only = TRUE;
147 happened = 0;
148 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
150 if (avail)
151 happened |= *p_sought & (POLLIN | POLLRDNORM);
153 else if (GetLastError () == ERROR_BROKEN_PIPE)
154 happened |= POLLHUP;
156 else
158 /* It was the write-end of the pipe. Check if it is writable.
159 If NtQueryInformationFile fails, optimistically assume the pipe is
160 writable. This could happen on Win9x, where NtQueryInformationFile
161 is not available, or if we inherit a pipe that doesn't permit
162 FILE_READ_ATTRIBUTES access on the write end (I think this should
163 not happen since WinXP SP2; WINE seems fine too). Otherwise,
164 ensure that enough space is available for atomic writes. */
165 memset (&iosb, 0, sizeof (iosb));
166 memset (&fpli, 0, sizeof (fpli));
168 if (!NtQueryInformationFile
169 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
170 FilePipeLocalInformation)
171 || fpli.WriteQuotaAvailable >= PIPE_BUF
172 || (fpli.OutboundQuota < PIPE_BUF &&
173 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
174 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
176 return happened;
178 case FILE_TYPE_CHAR:
179 ret = WaitForSingleObject (h, 0);
180 if (!IsConsoleHandle (h))
181 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
183 nbuffer = avail = 0;
184 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
185 if (bRet)
187 /* Input buffer. */
188 *p_sought &= POLLIN | POLLRDNORM;
189 if (nbuffer == 0)
190 return POLLHUP;
191 if (!*p_sought)
192 return 0;
194 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
195 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
196 if (!bRet || avail == 0)
197 return POLLHUP;
199 for (i = 0; i < avail; i++)
200 if (irbuffer[i].EventType == KEY_EVENT)
201 return *p_sought;
202 return 0;
204 else
206 /* Screen buffer. */
207 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
208 return *p_sought;
211 default:
212 ret = WaitForSingleObject (h, 0);
213 if (ret == WAIT_OBJECT_0)
214 return *p_sought & ~(POLLPRI | POLLRDBAND);
216 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
220 /* Convert fd_sets returned by select into revents values. */
222 static int
223 win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
225 int happened = 0;
227 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
228 happened |= (POLLIN | POLLRDNORM) & sought;
230 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
232 int r, error;
234 char data[64];
235 WSASetLastError (0);
236 r = recv (h, data, sizeof (data), MSG_PEEK);
237 error = WSAGetLastError ();
238 WSASetLastError (0);
240 if (r > 0 || error == WSAENOTCONN)
241 happened |= (POLLIN | POLLRDNORM) & sought;
243 /* Distinguish hung-up sockets from other errors. */
244 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
245 || error == WSAECONNABORTED || error == WSAENETRESET)
246 happened |= POLLHUP;
248 else
249 happened |= POLLERR;
252 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
253 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
255 if (lNetworkEvents & FD_OOB)
256 happened |= (POLLPRI | POLLRDBAND) & sought;
258 return happened;
261 #else /* !MinGW */
263 /* Convert select(2) returned fd_sets into poll(2) revents values. */
264 static int
265 compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
267 int happened = 0;
268 if (FD_ISSET (fd, rfds))
270 int r;
271 int socket_errno;
273 # if defined __MACH__ && defined __APPLE__
274 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
275 for some kinds of descriptors. Detect if this descriptor is a
276 connected socket, a server socket, or something else using a
277 0-byte recv, and use ioctl(2) to detect POLLHUP. */
278 r = recv (fd, NULL, 0, MSG_PEEK);
279 socket_errno = (r < 0) ? errno : 0;
280 if (r == 0 || socket_errno == ENOTSOCK)
281 ioctl (fd, FIONREAD, &r);
282 # else
283 char data[64];
284 r = recv (fd, data, sizeof (data), MSG_PEEK);
285 socket_errno = (r < 0) ? errno : 0;
286 # endif
287 if (r == 0)
288 happened |= POLLHUP;
290 /* If the event happened on an unconnected server socket,
291 that's fine. */
292 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
293 happened |= (POLLIN | POLLRDNORM) & sought;
295 /* Distinguish hung-up sockets from other errors. */
296 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
297 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
298 happened |= POLLHUP;
300 else
301 happened |= POLLERR;
304 if (FD_ISSET (fd, wfds))
305 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
307 if (FD_ISSET (fd, efds))
308 happened |= (POLLPRI | POLLRDBAND) & sought;
310 return happened;
312 #endif /* !MinGW */
315 poll (pfd, nfd, timeout)
316 struct pollfd *pfd;
317 nfds_t nfd;
318 int timeout;
320 #ifndef WIN32_NATIVE
321 fd_set rfds, wfds, efds;
322 struct timeval tv;
323 struct timeval *ptv;
324 int maxfd, rc;
325 nfds_t i;
327 # ifdef _SC_OPEN_MAX
328 static int sc_open_max = -1;
330 if (nfd < 0
331 || (nfd > sc_open_max
332 && (sc_open_max != -1
333 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
335 errno = EINVAL;
336 return -1;
338 # else /* !_SC_OPEN_MAX */
339 # ifdef OPEN_MAX
340 if (nfd < 0 || nfd > OPEN_MAX)
342 errno = EINVAL;
343 return -1;
345 # endif /* OPEN_MAX -- else, no check is needed */
346 # endif /* !_SC_OPEN_MAX */
348 /* EFAULT is not necessary to implement, but let's do it in the
349 simplest case. */
350 if (!pfd)
352 errno = EFAULT;
353 return -1;
356 /* convert timeout number into a timeval structure */
357 if (timeout == 0)
359 ptv = &tv;
360 ptv->tv_sec = 0;
361 ptv->tv_usec = 0;
363 else if (timeout > 0)
365 ptv = &tv;
366 ptv->tv_sec = timeout / 1000;
367 ptv->tv_usec = (timeout % 1000) * 1000;
369 else if (timeout == INFTIM)
370 /* wait forever */
371 ptv = NULL;
372 else
374 errno = EINVAL;
375 return -1;
378 /* create fd sets and determine max fd */
379 maxfd = -1;
380 FD_ZERO (&rfds);
381 FD_ZERO (&wfds);
382 FD_ZERO (&efds);
383 for (i = 0; i < nfd; i++)
385 if (pfd[i].fd < 0)
386 continue;
388 if (pfd[i].events & (POLLIN | POLLRDNORM))
389 FD_SET (pfd[i].fd, &rfds);
391 /* see select(2): "the only exceptional condition detectable
392 is out-of-band data received on a socket", hence we push
393 POLLWRBAND events onto wfds instead of efds. */
394 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
395 FD_SET (pfd[i].fd, &wfds);
396 if (pfd[i].events & (POLLPRI | POLLRDBAND))
397 FD_SET (pfd[i].fd, &efds);
398 if (pfd[i].fd >= maxfd
399 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
400 | POLLRDNORM | POLLRDBAND
401 | POLLWRNORM | POLLWRBAND)))
403 maxfd = pfd[i].fd;
404 if (maxfd > FD_SETSIZE)
406 errno = EOVERFLOW;
407 return -1;
412 /* examine fd sets */
413 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
414 if (rc < 0)
415 return rc;
417 /* establish results */
418 rc = 0;
419 for (i = 0; i < nfd; i++)
420 if (pfd[i].fd < 0)
421 pfd[i].revents = 0;
422 else
424 int happened = compute_revents (pfd[i].fd, pfd[i].events,
425 &rfds, &wfds, &efds);
426 if (happened)
428 pfd[i].revents = happened;
429 rc++;
433 return rc;
434 #else
435 static struct timeval tv0;
436 static HANDLE hEvent;
437 WSANETWORKEVENTS ev;
438 HANDLE h, handle_array[FD_SETSIZE + 2];
439 DWORD ret, wait_timeout, nhandles;
440 fd_set rfds, wfds, xfds;
441 BOOL poll_again;
442 MSG msg;
443 int rc = 0;
444 nfds_t i;
446 if (nfd < 0 || timeout < -1)
448 errno = EINVAL;
449 return -1;
452 if (!hEvent)
453 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
455 handle_array[0] = hEvent;
456 nhandles = 1;
457 FD_ZERO (&rfds);
458 FD_ZERO (&wfds);
459 FD_ZERO (&xfds);
461 /* Classify socket handles and create fd sets. */
462 for (i = 0; i < nfd; i++)
464 int sought = pfd[i].events;
465 pfd[i].revents = 0;
466 if (pfd[i].fd < 0)
467 continue;
468 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
469 | POLLPRI | POLLRDBAND)))
470 continue;
472 h = (HANDLE) _get_osfhandle (pfd[i].fd);
473 assert (h != NULL);
474 if (IsSocketHandle (h))
476 int requested = FD_CLOSE;
478 /* see above; socket handles are mapped onto select. */
479 if (sought & (POLLIN | POLLRDNORM))
481 requested |= FD_READ | FD_ACCEPT;
482 FD_SET ((SOCKET) h, &rfds);
484 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
486 requested |= FD_WRITE | FD_CONNECT;
487 FD_SET ((SOCKET) h, &wfds);
489 if (sought & (POLLPRI | POLLRDBAND))
491 requested |= FD_OOB;
492 FD_SET ((SOCKET) h, &xfds);
495 if (requested)
496 WSAEventSelect ((SOCKET) h, hEvent, requested);
498 else
500 /* Poll now. If we get an event, do not poll again. Also,
501 screen buffer handles are waitable, and they'll block until
502 a character is available. win32_compute_revents eliminates
503 bits for the "wrong" direction. */
504 pfd[i].revents = win32_compute_revents (h, &sought);
505 if (sought)
506 handle_array[nhandles++] = h;
507 if (pfd[i].revents)
508 timeout = 0;
512 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
514 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
515 no need to call select again. */
516 poll_again = FALSE;
517 wait_timeout = 0;
519 else
521 poll_again = TRUE;
522 if (timeout == INFTIM)
523 wait_timeout = INFINITE;
524 else
525 wait_timeout = timeout;
528 for (;;)
530 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
531 wait_timeout, QS_ALLINPUT);
533 if (ret == WAIT_OBJECT_0 + nhandles)
535 /* new input of some other kind */
536 BOOL bRet;
537 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
539 TranslateMessage (&msg);
540 DispatchMessage (&msg);
543 else
544 break;
547 if (poll_again)
548 select (0, &rfds, &wfds, &xfds, &tv0);
550 /* Place a sentinel at the end of the array. */
551 handle_array[nhandles] = NULL;
552 nhandles = 1;
553 for (i = 0; i < nfd; i++)
555 int happened;
557 if (pfd[i].fd < 0)
558 continue;
559 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
560 POLLOUT | POLLWRNORM | POLLWRBAND)))
561 continue;
563 h = (HANDLE) _get_osfhandle (pfd[i].fd);
564 if (h != handle_array[nhandles])
566 /* It's a socket. */
567 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
568 WSAEventSelect ((SOCKET) h, 0, 0);
570 /* If we're lucky, WSAEnumNetworkEvents already provided a way
571 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
572 if (FD_ISSET ((SOCKET) h, &rfds)
573 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
574 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
575 if (FD_ISSET ((SOCKET) h, &wfds))
576 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
577 if (FD_ISSET ((SOCKET) h, &xfds))
578 ev.lNetworkEvents |= FD_OOB;
580 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
581 ev.lNetworkEvents);
583 else
585 /* Not a socket. */
586 int sought = pfd[i].events;
587 happened = win32_compute_revents (h, &sought);
588 nhandles++;
591 if ((pfd[i].revents |= happened) != 0)
592 rc++;
595 return rc;
596 #endif