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