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