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