ae03b74a6f4e9c8ff6d519d9a784ab6b84179872
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
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.
12
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.
17
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. */
21
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
26
27#if defined(WIN32)
28# include <malloc.h>
29#endif
30
31#include <sys/types.h>
32
33/* Specification. */
34#include <poll.h>
35
36#include <errno.h>
37#include <limits.h>
38#include <assert.h>
39
40#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
41# define WIN32_NATIVE
42# if defined (_MSC_VER) && !defined(_WIN32_WINNT)
43# define _WIN32_WINNT 0x0502
44# endif
45# include <winsock2.h>
46# include <windows.h>
47# include <io.h>
48# include <stdio.h>
49# include <conio.h>
50#else
51# include <sys/time.h>
52# include <sys/socket.h>
53# ifndef NO_SYS_SELECT_H
54# include <sys/select.h>
55# endif
56# include <unistd.h>
57#endif
58
59#ifdef HAVE_SYS_IOCTL_H
60# include <sys/ioctl.h>
61#endif
62#ifdef HAVE_SYS_FILIO_H
63# include <sys/filio.h>
64#endif
65
66#include <time.h>
67
68#ifndef INFTIM
69# define INFTIM (-1)
70#endif
71
72/* BeOS does not have MSG_PEEK. */
73#ifndef MSG_PEEK
74# define MSG_PEEK 0
75#endif
76
77#ifdef WIN32_NATIVE
78
79#define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
80
81static BOOL
82IsSocketHandle (HANDLE h)
83{
84 WSANETWORKEVENTS ev;
85
86 if (IsConsoleHandle (h))
87 return FALSE;
88
89 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
90 WSAEnumNetworkEvents instead distinguishes the two correctly. */
91 ev.lNetworkEvents = 0xDEADBEEF;
92 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
93 return ev.lNetworkEvents != 0xDEADBEEF;
94}
95
96/* Declare data structures for ntdll functions. */
97typedef struct _FILE_PIPE_LOCAL_INFORMATION {
98 ULONG NamedPipeType;
99 ULONG NamedPipeConfiguration;
100 ULONG MaximumInstances;
101 ULONG CurrentInstances;
102 ULONG InboundQuota;
103 ULONG ReadDataAvailable;
104 ULONG OutboundQuota;
105 ULONG WriteQuotaAvailable;
106 ULONG NamedPipeState;
107 ULONG NamedPipeEnd;
108} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
109
110typedef struct _IO_STATUS_BLOCK
111{
112 union {
113 DWORD Status;
114 PVOID Pointer;
115 } u;
116 ULONG_PTR Information;
117} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
118
119typedef enum _FILE_INFORMATION_CLASS {
120 FilePipeLocalInformation = 24
121} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
122
123typedef DWORD (WINAPI *PNtQueryInformationFile)
124 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
125
126# ifndef PIPE_BUF
127# define PIPE_BUF 512
128# endif
129
130/* Compute revents values for file handle H. If some events cannot happen
131 for the handle, eliminate them from *P_SOUGHT. */
132
133static int
134win32_compute_revents (HANDLE h, int *p_sought)
135{
136 int i, ret, happened;
137 INPUT_RECORD *irbuffer;
138 DWORD avail, nbuffer;
139 BOOL bRet;
140 IO_STATUS_BLOCK iosb;
141 FILE_PIPE_LOCAL_INFORMATION fpli;
142 static PNtQueryInformationFile NtQueryInformationFile;
143 static BOOL once_only;
144
145 switch (GetFileType (h))
146 {
147 case FILE_TYPE_PIPE:
148 if (!once_only)
149 {
150 NtQueryInformationFile = (PNtQueryInformationFile)
151 GetProcAddress (GetModuleHandle ("ntdll.dll"),
152 "NtQueryInformationFile");
153 once_only = TRUE;
154 }
155
156 happened = 0;
157 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
158 {
159 if (avail)
160 happened |= *p_sought & (POLLIN | POLLRDNORM);
161 }
162 else if (GetLastError () == ERROR_BROKEN_PIPE)
163 happened |= POLLHUP;
164
165 else
166 {
167 /* It was the write-end of the pipe. Check if it is writable.
168 If NtQueryInformationFile fails, optimistically assume the pipe is
169 writable. This could happen on Win9x, where NtQueryInformationFile
170 is not available, or if we inherit a pipe that doesn't permit
171 FILE_READ_ATTRIBUTES access on the write end (I think this should
172 not happen since WinXP SP2; WINE seems fine too). Otherwise,
173 ensure that enough space is available for atomic writes. */
174 memset (&iosb, 0, sizeof (iosb));
175 memset (&fpli, 0, sizeof (fpli));
176
177 if (!NtQueryInformationFile
178 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
179 FilePipeLocalInformation)
180 || fpli.WriteQuotaAvailable >= PIPE_BUF
181 || (fpli.OutboundQuota < PIPE_BUF &&
182 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
183 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
184 }
185 return happened;
186
187 case FILE_TYPE_CHAR:
188 ret = WaitForSingleObject (h, 0);
189 if (!IsConsoleHandle (h))
190 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
191
192 nbuffer = avail = 0;
193 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
194 if (bRet)
195 {
196 /* Input buffer. */
197 *p_sought &= POLLIN | POLLRDNORM;
198 if (nbuffer == 0)
199 return POLLHUP;
200 if (!*p_sought)
201 return 0;
202
203 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
204 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
205 if (!bRet || avail == 0)
206 return POLLHUP;
207
208 for (i = 0; i < avail; i++)
209 if (irbuffer[i].EventType == KEY_EVENT)
210 return *p_sought;
211 return 0;
212 }
213 else
214 {
215 /* Screen buffer. */
216 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
217 return *p_sought;
218 }
219
220 default:
221 ret = WaitForSingleObject (h, 0);
222 if (ret == WAIT_OBJECT_0)
223 return *p_sought & ~(POLLPRI | POLLRDBAND);
224
225 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
226 }
227}
228
229/* Convert fd_sets returned by select into revents values. */
230
231static int
232win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
233{
234 int happened = 0;
235
236 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
237 happened |= (POLLIN | POLLRDNORM) & sought;
238
239 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
240 {
241 int r, error;
242
243 char data[64];
244 WSASetLastError (0);
245 r = recv (h, data, sizeof (data), MSG_PEEK);
246 error = WSAGetLastError ();
247 WSASetLastError (0);
248
249 if (r > 0 || error == WSAENOTCONN)
250 happened |= (POLLIN | POLLRDNORM) & sought;
251
252 /* Distinguish hung-up sockets from other errors. */
253 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
254 || error == WSAECONNABORTED || error == WSAENETRESET)
255 happened |= POLLHUP;
256
257 else
258 happened |= POLLERR;
259 }
260
261 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
262 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
263
264 if (lNetworkEvents & FD_OOB)
265 happened |= (POLLPRI | POLLRDBAND) & sought;
266
267 return happened;
268}
269
270#else /* !MinGW */
271
272/* Convert select(2) returned fd_sets into poll(2) revents values. */
273static int
274compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
275{
276 int happened = 0;
277 if (FD_ISSET (fd, rfds))
278 {
279 int r;
280 int socket_errno;
281
282# if defined __MACH__ && defined __APPLE__
283 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
284 for some kinds of descriptors. Detect if this descriptor is a
285 connected socket, a server socket, or something else using a
286 0-byte recv, and use ioctl(2) to detect POLLHUP. */
287 r = recv (fd, NULL, 0, MSG_PEEK);
288 socket_errno = (r < 0) ? errno : 0;
289 if (r == 0 || socket_errno == ENOTSOCK)
290 ioctl (fd, FIONREAD, &r);
291# else
292 char data[64];
293 r = recv (fd, data, sizeof (data), MSG_PEEK);
294 socket_errno = (r < 0) ? errno : 0;
295# endif
296 if (r == 0)
297 happened |= POLLHUP;
298
299 /* If the event happened on an unconnected server socket,
300 that's fine. */
301 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
302 happened |= (POLLIN | POLLRDNORM) & sought;
303
304 /* Distinguish hung-up sockets from other errors. */
305 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
306 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
307 happened |= POLLHUP;
308
309 /* some systems can't use recv() on non-socket, including HP NonStop */
310 else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
311 happened |= (POLLIN | POLLRDNORM) & sought;
312
313 else
314 happened |= POLLERR;
315 }
316
317 if (FD_ISSET (fd, wfds))
318 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
319
320 if (FD_ISSET (fd, efds))
321 happened |= (POLLPRI | POLLRDBAND) & sought;
322
323 return happened;
324}
325#endif /* !MinGW */
326
327int
328poll (struct pollfd *pfd, nfds_t nfd, int timeout)
329{
330#ifndef WIN32_NATIVE
331 fd_set rfds, wfds, efds;
332 struct timeval tv;
333 struct timeval *ptv;
334 int maxfd, rc;
335 nfds_t i;
336
337# ifdef _SC_OPEN_MAX
338 static int sc_open_max = -1;
339
340 if (nfd < 0
341 || (nfd > sc_open_max
342 && (sc_open_max != -1
343 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
344 {
345 errno = EINVAL;
346 return -1;
347 }
348# else /* !_SC_OPEN_MAX */
349# ifdef OPEN_MAX
350 if (nfd < 0 || nfd > OPEN_MAX)
351 {
352 errno = EINVAL;
353 return -1;
354 }
355# endif /* OPEN_MAX -- else, no check is needed */
356# endif /* !_SC_OPEN_MAX */
357
358 /* EFAULT is not necessary to implement, but let's do it in the
359 simplest case. */
360 if (!pfd && nfd)
361 {
362 errno = EFAULT;
363 return -1;
364 }
365
366 /* convert timeout number into a timeval structure */
367 if (timeout == 0)
368 {
369 ptv = &tv;
370 ptv->tv_sec = 0;
371 ptv->tv_usec = 0;
372 }
373 else if (timeout > 0)
374 {
375 ptv = &tv;
376 ptv->tv_sec = timeout / 1000;
377 ptv->tv_usec = (timeout % 1000) * 1000;
378 }
379 else if (timeout == INFTIM)
380 /* wait forever */
381 ptv = NULL;
382 else
383 {
384 errno = EINVAL;
385 return -1;
386 }
387
388 /* create fd sets and determine max fd */
389 maxfd = -1;
390 FD_ZERO (&rfds);
391 FD_ZERO (&wfds);
392 FD_ZERO (&efds);
393 for (i = 0; i < nfd; i++)
394 {
395 if (pfd[i].fd < 0)
396 continue;
397
398 if (pfd[i].events & (POLLIN | POLLRDNORM))
399 FD_SET (pfd[i].fd, &rfds);
400
401 /* see select(2): "the only exceptional condition detectable
402 is out-of-band data received on a socket", hence we push
403 POLLWRBAND events onto wfds instead of efds. */
404 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
405 FD_SET (pfd[i].fd, &wfds);
406 if (pfd[i].events & (POLLPRI | POLLRDBAND))
407 FD_SET (pfd[i].fd, &efds);
408 if (pfd[i].fd >= maxfd
409 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
410 | POLLRDNORM | POLLRDBAND
411 | POLLWRNORM | POLLWRBAND)))
412 {
413 maxfd = pfd[i].fd;
414 if (maxfd > FD_SETSIZE)
415 {
416 errno = EOVERFLOW;
417 return -1;
418 }
419 }
420 }
421
422 /* examine fd sets */
423 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
424 if (rc < 0)
425 return rc;
426
427 /* establish results */
428 rc = 0;
429 for (i = 0; i < nfd; i++)
430 if (pfd[i].fd < 0)
431 pfd[i].revents = 0;
432 else
433 {
434 int happened = compute_revents (pfd[i].fd, pfd[i].events,
435 &rfds, &wfds, &efds);
436 if (happened)
437 {
438 pfd[i].revents = happened;
439 rc++;
440 }
441 else
442 {
443 pfd[i].revents = 0;
444 }
445 }
446
447 return rc;
448#else
449 static struct timeval tv0;
450 static HANDLE hEvent;
451 WSANETWORKEVENTS ev;
452 HANDLE h, handle_array[FD_SETSIZE + 2];
453 DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0;
454 fd_set rfds, wfds, xfds;
455 BOOL poll_again;
456 MSG msg;
457 int rc = 0;
458 nfds_t i;
459
460 if (nfd < 0 || timeout < -1)
461 {
462 errno = EINVAL;
463 return -1;
464 }
465
466 if (timeout != INFTIM)
467 {
468 orig_timeout = timeout;
469 start = GetTickCount();
470 }
471
472 if (!hEvent)
473 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
474
475restart:
476 handle_array[0] = hEvent;
477 nhandles = 1;
478 FD_ZERO (&rfds);
479 FD_ZERO (&wfds);
480 FD_ZERO (&xfds);
481
482 /* Classify socket handles and create fd sets. */
483 for (i = 0; i < nfd; i++)
484 {
485 int sought = pfd[i].events;
486 pfd[i].revents = 0;
487 if (pfd[i].fd < 0)
488 continue;
489 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
490 | POLLPRI | POLLRDBAND)))
491 continue;
492
493 h = (HANDLE) _get_osfhandle (pfd[i].fd);
494 assert (h != NULL);
495 if (IsSocketHandle (h))
496 {
497 int requested = FD_CLOSE;
498
499 /* see above; socket handles are mapped onto select. */
500 if (sought & (POLLIN | POLLRDNORM))
501 {
502 requested |= FD_READ | FD_ACCEPT;
503 FD_SET ((SOCKET) h, &rfds);
504 }
505 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
506 {
507 requested |= FD_WRITE | FD_CONNECT;
508 FD_SET ((SOCKET) h, &wfds);
509 }
510 if (sought & (POLLPRI | POLLRDBAND))
511 {
512 requested |= FD_OOB;
513 FD_SET ((SOCKET) h, &xfds);
514 }
515
516 if (requested)
517 WSAEventSelect ((SOCKET) h, hEvent, requested);
518 }
519 else
520 {
521 /* Poll now. If we get an event, do not poll again. Also,
522 screen buffer handles are waitable, and they'll block until
523 a character is available. win32_compute_revents eliminates
524 bits for the "wrong" direction. */
525 pfd[i].revents = win32_compute_revents (h, &sought);
526 if (sought)
527 handle_array[nhandles++] = h;
528 if (pfd[i].revents)
529 timeout = 0;
530 }
531 }
532
533 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
534 {
535 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
536 no need to call select again. */
537 poll_again = FALSE;
538 wait_timeout = 0;
539 }
540 else
541 {
542 poll_again = TRUE;
543 if (timeout == INFTIM)
544 wait_timeout = INFINITE;
545 else
546 wait_timeout = timeout;
547 }
548
549 for (;;)
550 {
551 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
552 wait_timeout, QS_ALLINPUT);
553
554 if (ret == WAIT_OBJECT_0 + nhandles)
555 {
556 /* new input of some other kind */
557 BOOL bRet;
558 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
559 {
560 TranslateMessage (&msg);
561 DispatchMessage (&msg);
562 }
563 }
564 else
565 break;
566 }
567
568 if (poll_again)
569 select (0, &rfds, &wfds, &xfds, &tv0);
570
571 /* Place a sentinel at the end of the array. */
572 handle_array[nhandles] = NULL;
573 nhandles = 1;
574 for (i = 0; i < nfd; i++)
575 {
576 int happened;
577
578 if (pfd[i].fd < 0)
579 continue;
580 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
581 POLLOUT | POLLWRNORM | POLLWRBAND)))
582 continue;
583
584 h = (HANDLE) _get_osfhandle (pfd[i].fd);
585 if (h != handle_array[nhandles])
586 {
587 /* It's a socket. */
588 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
589 WSAEventSelect ((SOCKET) h, NULL, 0);
590
591 /* If we're lucky, WSAEnumNetworkEvents already provided a way
592 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
593 if (FD_ISSET ((SOCKET) h, &rfds)
594 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
595 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
596 if (FD_ISSET ((SOCKET) h, &wfds))
597 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
598 if (FD_ISSET ((SOCKET) h, &xfds))
599 ev.lNetworkEvents |= FD_OOB;
600
601 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
602 ev.lNetworkEvents);
603 }
604 else
605 {
606 /* Not a socket. */
607 int sought = pfd[i].events;
608 happened = win32_compute_revents (h, &sought);
609 nhandles++;
610 }
611
612 if ((pfd[i].revents |= happened) != 0)
613 rc++;
614 }
615
616 if (!rc && orig_timeout && timeout != INFTIM)
617 {
618 elapsed = GetTickCount() - start;
619 timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed;
620 }
621
622 if (!rc && timeout)
623 {
624 SleepEx (1, TRUE);
625 goto restart;
626 }
627
628 return rc;
629#endif
630}