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