compat / poll / poll.con commit Merge branch 'jc/no-cmd-as-subroutine' (22ddc4b)
   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        else
 442          {
 443            pfd[i].revents = 0;
 444          }
 445      }
 446
 447  return rc;
 448#else
 449  static struct timeval tv0;
 450  static HANDLE hEvent;
 451  WSANETWORKEVENTS ev;
 452  HANDLE h, handle_array[FD_SETSIZE + 2];
 453  DWORD ret, wait_timeout, nhandles, start = 0, elapsed, orig_timeout = 0;
 454  fd_set rfds, wfds, xfds;
 455  BOOL poll_again;
 456  MSG msg;
 457  int rc = 0;
 458  nfds_t i;
 459
 460  if (nfd < 0 || timeout < -1)
 461    {
 462      errno = EINVAL;
 463      return -1;
 464    }
 465
 466  if (timeout != INFTIM)
 467    {
 468      orig_timeout = timeout;
 469      start = GetTickCount();
 470    }
 471
 472  if (!hEvent)
 473    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 474
 475restart:
 476  handle_array[0] = hEvent;
 477  nhandles = 1;
 478  FD_ZERO (&rfds);
 479  FD_ZERO (&wfds);
 480  FD_ZERO (&xfds);
 481
 482  /* Classify socket handles and create fd sets. */
 483  for (i = 0; i < nfd; i++)
 484    {
 485      int sought = pfd[i].events;
 486      pfd[i].revents = 0;
 487      if (pfd[i].fd < 0)
 488        continue;
 489      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
 490                      | POLLPRI | POLLRDBAND)))
 491        continue;
 492
 493      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 494      assert (h != NULL);
 495      if (IsSocketHandle (h))
 496        {
 497          int requested = FD_CLOSE;
 498
 499          /* see above; socket handles are mapped onto select.  */
 500          if (sought & (POLLIN | POLLRDNORM))
 501            {
 502              requested |= FD_READ | FD_ACCEPT;
 503              FD_SET ((SOCKET) h, &rfds);
 504            }
 505          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
 506            {
 507              requested |= FD_WRITE | FD_CONNECT;
 508              FD_SET ((SOCKET) h, &wfds);
 509            }
 510          if (sought & (POLLPRI | POLLRDBAND))
 511            {
 512              requested |= FD_OOB;
 513              FD_SET ((SOCKET) h, &xfds);
 514            }
 515
 516          if (requested)
 517            WSAEventSelect ((SOCKET) h, hEvent, requested);
 518        }
 519      else
 520        {
 521          /* Poll now.  If we get an event, do not poll again.  Also,
 522             screen buffer handles are waitable, and they'll block until
 523             a character is available.  win32_compute_revents eliminates
 524             bits for the "wrong" direction. */
 525          pfd[i].revents = win32_compute_revents (h, &sought);
 526          if (sought)
 527            handle_array[nhandles++] = h;
 528          if (pfd[i].revents)
 529            timeout = 0;
 530        }
 531    }
 532
 533  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
 534    {
 535      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
 536         no need to call select again.  */
 537      poll_again = FALSE;
 538      wait_timeout = 0;
 539    }
 540  else
 541    {
 542      poll_again = TRUE;
 543      if (timeout == INFTIM)
 544        wait_timeout = INFINITE;
 545      else
 546        wait_timeout = timeout;
 547    }
 548
 549  for (;;)
 550    {
 551      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
 552                                       wait_timeout, QS_ALLINPUT);
 553
 554      if (ret == WAIT_OBJECT_0 + nhandles)
 555        {
 556          /* new input of some other kind */
 557          BOOL bRet;
 558          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
 559            {
 560              TranslateMessage (&msg);
 561              DispatchMessage (&msg);
 562            }
 563        }
 564      else
 565        break;
 566    }
 567
 568  if (poll_again)
 569    select (0, &rfds, &wfds, &xfds, &tv0);
 570
 571  /* Place a sentinel at the end of the array.  */
 572  handle_array[nhandles] = NULL;
 573  nhandles = 1;
 574  for (i = 0; i < nfd; i++)
 575    {
 576      int happened;
 577
 578      if (pfd[i].fd < 0)
 579        continue;
 580      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
 581                             POLLOUT | POLLWRNORM | POLLWRBAND)))
 582        continue;
 583
 584      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 585      if (h != handle_array[nhandles])
 586        {
 587          /* It's a socket.  */
 588          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
 589          WSAEventSelect ((SOCKET) h, NULL, 0);
 590
 591          /* If we're lucky, WSAEnumNetworkEvents already provided a way
 592             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
 593          if (FD_ISSET ((SOCKET) h, &rfds)
 594              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
 595            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
 596          if (FD_ISSET ((SOCKET) h, &wfds))
 597            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
 598          if (FD_ISSET ((SOCKET) h, &xfds))
 599            ev.lNetworkEvents |= FD_OOB;
 600
 601          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
 602                                                   ev.lNetworkEvents);
 603        }
 604      else
 605        {
 606          /* Not a socket.  */
 607          int sought = pfd[i].events;
 608          happened = win32_compute_revents (h, &sought);
 609          nhandles++;
 610        }
 611
 612       if ((pfd[i].revents |= happened) != 0)
 613        rc++;
 614    }
 615
 616  if (!rc && orig_timeout && timeout != INFTIM)
 617    {
 618      elapsed = GetTickCount() - start;
 619      timeout = elapsed >= orig_timeout ? 0 : orig_timeout - elapsed;
 620    }
 621
 622  if (!rc && timeout)
 623    {
 624      SleepEx (1, TRUE);
 625      goto restart;
 626    }
 627
 628  return rc;
 629#endif
 630}