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