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