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