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 <config.h>
28#include <alloca.h>
29
30#include <sys/types.h>
31#include "poll.h"
32#include <errno.h>
33#include <limits.h>
34#include <assert.h>
35
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
49
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
56
57#include <time.h>
58
59#ifndef INFTIM
60# define INFTIM (-1)
61#endif
62
63/* BeOS does not have MSG_PEEK. */
64#ifndef MSG_PEEK
65# define MSG_PEEK 0
66#endif
67
68#ifdef WIN32_NATIVE
69
70#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
71
72static BOOL
73IsSocketHandle (HANDLE h)
74{
75 WSANETWORKEVENTS ev;
76
77 if (IsConsoleHandle (h))
78 return FALSE;
79
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;
85}
86
87/* Declare data structures for ntdll functions. */
88typedef 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;
100
101typedef struct _IO_STATUS_BLOCK
102{
103 union {
104 DWORD Status;
105 PVOID Pointer;
106 } u;
107 ULONG_PTR Information;
108} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
109
110typedef enum _FILE_INFORMATION_CLASS {
111 FilePipeLocalInformation = 24
112} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
113
114typedef DWORD (WINAPI *PNtQueryInformationFile)
115 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
116
117# ifndef PIPE_BUF
118# define PIPE_BUF 512
119# endif
120
121/* Compute revents values for file handle H. If some events cannot happen
122 for the handle, eliminate them from *P_SOUGHT. */
123
124static int
125win32_compute_revents (HANDLE h, int *p_sought)
126{
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;
135
136 switch (GetFileType (h))
137 {
138 case FILE_TYPE_PIPE:
139 if (!once_only)
140 {
141 NtQueryInformationFile = (PNtQueryInformationFile)
142 GetProcAddress (GetModuleHandle ("ntdll.dll"),
143 "NtQueryInformationFile");
144 once_only = TRUE;
145 }
146
147 happened = 0;
148 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
149 {
150 if (avail)
151 happened |= *p_sought & (POLLIN | POLLRDNORM);
152 }
153 else if (GetLastError () == ERROR_BROKEN_PIPE)
154 happened |= POLLHUP;
155
156 else
157 {
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));
167
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);
175 }
176 return happened;
177
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;
182
183 nbuffer = avail = 0;
184 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
185 if (bRet)
186 {
187 /* Input buffer. */
188 *p_sought &= POLLIN | POLLRDNORM;
189 if (nbuffer == 0)
190 return POLLHUP;
191 if (!*p_sought)
192 return 0;
193
194 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
195 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
196 if (!bRet || avail == 0)
197 return POLLHUP;
198
199 for (i = 0; i < avail; i++)
200 if (irbuffer[i].EventType == KEY_EVENT)
201 return *p_sought;
202 return 0;
203 }
204 else
205 {
206 /* Screen buffer. */
207 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
208 return *p_sought;
209 }
210
211 default:
212 ret = WaitForSingleObject (h, 0);
213 if (ret == WAIT_OBJECT_0)
214 return *p_sought & ~(POLLPRI | POLLRDBAND);
215
216 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
217 }
218}
219
220/* Convert fd_sets returned by select into revents values. */
221
222static int
223win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
224{
225 int happened = 0;
226
227 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
228 happened |= (POLLIN | POLLRDNORM) & sought;
229
230 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
231 {
232 int r, error;
233
234 char data[64];
235 WSASetLastError (0);
236 r = recv (h, data, sizeof (data), MSG_PEEK);
237 error = WSAGetLastError ();
238 WSASetLastError (0);
239
240 if (r > 0 || error == WSAENOTCONN)
241 happened |= (POLLIN | POLLRDNORM) & sought;
242
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;
247
248 else
249 happened |= POLLERR;
250 }
251
252 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
253 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
254
255 if (lNetworkEvents & FD_OOB)
256 happened |= (POLLPRI | POLLRDBAND) & sought;
257
258 return happened;
259}
260
261#else /* !MinGW */
262
263/* Convert select(2) returned fd_sets into poll(2) revents values. */
264static int
265compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
266{
267 int happened = 0;
268 if (FD_ISSET (fd, rfds))
269 {
270 int r;
271 int socket_errno;
272
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;
289
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;
294
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;
299
300 else
301 happened |= POLLERR;
302 }
303
304 if (FD_ISSET (fd, wfds))
305 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
306
307 if (FD_ISSET (fd, efds))
308 happened |= (POLLPRI | POLLRDBAND) & sought;
309
310 return happened;
311}
312#endif /* !MinGW */
313
314int
315poll (pfd, nfd, timeout)
316 struct pollfd *pfd;
317 nfds_t nfd;
318 int timeout;
319{
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;
326
327# ifdef _SC_OPEN_MAX
328 static int sc_open_max = -1;
329
330 if (nfd < 0
331 || (nfd > sc_open_max
332 && (sc_open_max != -1
333 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
334 {
335 errno = EINVAL;
336 return -1;
337 }
338# else /* !_SC_OPEN_MAX */
339# ifdef OPEN_MAX
340 if (nfd < 0 || nfd > OPEN_MAX)
341 {
342 errno = EINVAL;
343 return -1;
344 }
345# endif /* OPEN_MAX -- else, no check is needed */
346# endif /* !_SC_OPEN_MAX */
347
348 /* EFAULT is not necessary to implement, but let's do it in the
349 simplest case. */
350 if (!pfd)
351 {
352 errno = EFAULT;
353 return -1;
354 }
355
356 /* convert timeout number into a timeval structure */
357 if (timeout == 0)
358 {
359 ptv = &tv;
360 ptv->tv_sec = 0;
361 ptv->tv_usec = 0;
362 }
363 else if (timeout > 0)
364 {
365 ptv = &tv;
366 ptv->tv_sec = timeout / 1000;
367 ptv->tv_usec = (timeout % 1000) * 1000;
368 }
369 else if (timeout == INFTIM)
370 /* wait forever */
371 ptv = NULL;
372 else
373 {
374 errno = EINVAL;
375 return -1;
376 }
377
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++)
384 {
385 if (pfd[i].fd < 0)
386 continue;
387
388 if (pfd[i].events & (POLLIN | POLLRDNORM))
389 FD_SET (pfd[i].fd, &rfds);
390
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)))
402 {
403 maxfd = pfd[i].fd;
404 if (maxfd > FD_SETSIZE)
405 {
406 errno = EOVERFLOW;
407 return -1;
408 }
409 }
410 }
411
412 /* examine fd sets */
413 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
414 if (rc < 0)
415 return rc;
416
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
423 {
424 int happened = compute_revents (pfd[i].fd, pfd[i].events,
425 &rfds, &wfds, &efds);
426 if (happened)
427 {
428 pfd[i].revents = happened;
429 rc++;
430 }
431 }
432
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;
445
446 if (nfd < 0 || timeout < -1)
447 {
448 errno = EINVAL;
449 return -1;
450 }
451
452 if (!hEvent)
453 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
454
455 handle_array[0] = hEvent;
456 nhandles = 1;
457 FD_ZERO (&rfds);
458 FD_ZERO (&wfds);
459 FD_ZERO (&xfds);
460
461 /* Classify socket handles and create fd sets. */
462 for (i = 0; i < nfd; i++)
463 {
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;
471
472 h = (HANDLE) _get_osfhandle (pfd[i].fd);
473 assert (h != NULL);
474 if (IsSocketHandle (h))
475 {
476 int requested = FD_CLOSE;
477
478 /* see above; socket handles are mapped onto select. */
479 if (sought & (POLLIN | POLLRDNORM))
480 {
481 requested |= FD_READ | FD_ACCEPT;
482 FD_SET ((SOCKET) h, &rfds);
483 }
484 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
485 {
486 requested |= FD_WRITE | FD_CONNECT;
487 FD_SET ((SOCKET) h, &wfds);
488 }
489 if (sought & (POLLPRI | POLLRDBAND))
490 {
491 requested |= FD_OOB;
492 FD_SET ((SOCKET) h, &xfds);
493 }
494
495 if (requested)
496 WSAEventSelect ((SOCKET) h, hEvent, requested);
497 }
498 else
499 {
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;
509 }
510 }
511
512 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
513 {
514 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
515 no need to call select again. */
516 poll_again = FALSE;
517 wait_timeout = 0;
518 }
519 else
520 {
521 poll_again = TRUE;
522 if (timeout == INFTIM)
523 wait_timeout = INFINITE;
524 else
525 wait_timeout = timeout;
526 }
527
528 for (;;)
529 {
530 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
531 wait_timeout, QS_ALLINPUT);
532
533 if (ret == WAIT_OBJECT_0 + nhandles)
534 {
535 /* new input of some other kind */
536 BOOL bRet;
537 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
538 {
539 TranslateMessage (&msg);
540 DispatchMessage (&msg);
541 }
542 }
543 else
544 break;
545 }
546
547 if (poll_again)
548 select (0, &rfds, &wfds, &xfds, &tv0);
549
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++)
554 {
555 int happened;
556
557 if (pfd[i].fd < 0)
558 continue;
559 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
560 POLLOUT | POLLWRNORM | POLLWRBAND)))
561 continue;
562
563 h = (HANDLE) _get_osfhandle (pfd[i].fd);
564 if (h != handle_array[nhandles])
565 {
566 /* It's a socket. */
567 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
568 WSAEventSelect ((SOCKET) h, 0, 0);
569
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;
579
580 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
581 ev.lNetworkEvents);
582 }
583 else
584 {
585 /* Not a socket. */
586 int sought = pfd[i].events;
587 happened = win32_compute_revents (h, &sought);
588 nhandles++;
589 }
590
591 if ((pfd[i].revents |= happened) != 0)
592 rc++;
593 }
594
595 return rc;
596#endif
597}