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