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