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"
36typedef 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
93static BOOL
94IsSocketHandle (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
108static HANDLE
109HandleFromFd (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.  */
119typedef 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
132typedef 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
141typedef enum _FILE_INFORMATION_CLASS {
142  FilePipeLocalInformation = 24
143} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
144
145typedef 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
155static int
156windows_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
254static int
255windows_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.  */
296static int
297compute_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
350int
351pa_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
481restart:
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