compat / poll / poll.con commit poll() exits too early with EFAULT if 1st arg is NULL (32fde65)
   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      else
 310        happened |= POLLERR;
 311    }
 312
 313  if (FD_ISSET (fd, wfds))
 314    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
 315
 316  if (FD_ISSET (fd, efds))
 317    happened |= (POLLPRI | POLLRDBAND) & sought;
 318
 319  return happened;
 320}
 321#endif /* !MinGW */
 322
 323int
 324poll (struct pollfd *pfd, nfds_t nfd, int timeout)
 325{
 326#ifndef WIN32_NATIVE
 327  fd_set rfds, wfds, efds;
 328  struct timeval tv;
 329  struct timeval *ptv;
 330  int maxfd, rc;
 331  nfds_t i;
 332
 333# ifdef _SC_OPEN_MAX
 334  static int sc_open_max = -1;
 335
 336  if (nfd < 0
 337      || (nfd > sc_open_max
 338          && (sc_open_max != -1
 339              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
 340    {
 341      errno = EINVAL;
 342      return -1;
 343    }
 344# else /* !_SC_OPEN_MAX */
 345#  ifdef OPEN_MAX
 346  if (nfd < 0 || nfd > OPEN_MAX)
 347    {
 348      errno = EINVAL;
 349      return -1;
 350    }
 351#  endif /* OPEN_MAX -- else, no check is needed */
 352# endif /* !_SC_OPEN_MAX */
 353
 354  /* EFAULT is not necessary to implement, but let's do it in the
 355     simplest case. */
 356  if (!pfd && nfd)
 357    {
 358      errno = EFAULT;
 359      return -1;
 360    }
 361
 362  /* convert timeout number into a timeval structure */
 363  if (timeout == 0)
 364    {
 365      ptv = &tv;
 366      ptv->tv_sec = 0;
 367      ptv->tv_usec = 0;
 368    }
 369  else if (timeout > 0)
 370    {
 371      ptv = &tv;
 372      ptv->tv_sec = timeout / 1000;
 373      ptv->tv_usec = (timeout % 1000) * 1000;
 374    }
 375  else if (timeout == INFTIM)
 376    /* wait forever */
 377    ptv = NULL;
 378  else
 379    {
 380      errno = EINVAL;
 381      return -1;
 382    }
 383
 384  /* create fd sets and determine max fd */
 385  maxfd = -1;
 386  FD_ZERO (&rfds);
 387  FD_ZERO (&wfds);
 388  FD_ZERO (&efds);
 389  for (i = 0; i < nfd; i++)
 390    {
 391      if (pfd[i].fd < 0)
 392        continue;
 393
 394      if (pfd[i].events & (POLLIN | POLLRDNORM))
 395        FD_SET (pfd[i].fd, &rfds);
 396
 397      /* see select(2): "the only exceptional condition detectable
 398         is out-of-band data received on a socket", hence we push
 399         POLLWRBAND events onto wfds instead of efds. */
 400      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
 401        FD_SET (pfd[i].fd, &wfds);
 402      if (pfd[i].events & (POLLPRI | POLLRDBAND))
 403        FD_SET (pfd[i].fd, &efds);
 404      if (pfd[i].fd >= maxfd
 405          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
 406                               | POLLRDNORM | POLLRDBAND
 407                               | POLLWRNORM | POLLWRBAND)))
 408        {
 409          maxfd = pfd[i].fd;
 410          if (maxfd > FD_SETSIZE)
 411            {
 412              errno = EOVERFLOW;
 413              return -1;
 414            }
 415        }
 416    }
 417
 418  /* examine fd sets */
 419  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
 420  if (rc < 0)
 421    return rc;
 422
 423  /* establish results */
 424  rc = 0;
 425  for (i = 0; i < nfd; i++)
 426    if (pfd[i].fd < 0)
 427      pfd[i].revents = 0;
 428    else
 429      {
 430        int happened = compute_revents (pfd[i].fd, pfd[i].events,
 431                                        &rfds, &wfds, &efds);
 432        if (happened)
 433          {
 434            pfd[i].revents = happened;
 435            rc++;
 436          }
 437      }
 438
 439  return rc;
 440#else
 441  static struct timeval tv0;
 442  static HANDLE hEvent;
 443  WSANETWORKEVENTS ev;
 444  HANDLE h, handle_array[FD_SETSIZE + 2];
 445  DWORD ret, wait_timeout, nhandles;
 446  fd_set rfds, wfds, xfds;
 447  BOOL poll_again;
 448  MSG msg;
 449  int rc = 0;
 450  nfds_t i;
 451
 452  if (nfd < 0 || timeout < -1)
 453    {
 454      errno = EINVAL;
 455      return -1;
 456    }
 457
 458  if (!hEvent)
 459    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 460
 461restart:
 462  handle_array[0] = hEvent;
 463  nhandles = 1;
 464  FD_ZERO (&rfds);
 465  FD_ZERO (&wfds);
 466  FD_ZERO (&xfds);
 467
 468  /* Classify socket handles and create fd sets. */
 469  for (i = 0; i < nfd; i++)
 470    {
 471      int sought = pfd[i].events;
 472      pfd[i].revents = 0;
 473      if (pfd[i].fd < 0)
 474        continue;
 475      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
 476                      | POLLPRI | POLLRDBAND)))
 477        continue;
 478
 479      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 480      assert (h != NULL);
 481      if (IsSocketHandle (h))
 482        {
 483          int requested = FD_CLOSE;
 484
 485          /* see above; socket handles are mapped onto select.  */
 486          if (sought & (POLLIN | POLLRDNORM))
 487            {
 488              requested |= FD_READ | FD_ACCEPT;
 489              FD_SET ((SOCKET) h, &rfds);
 490            }
 491          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
 492            {
 493              requested |= FD_WRITE | FD_CONNECT;
 494              FD_SET ((SOCKET) h, &wfds);
 495            }
 496          if (sought & (POLLPRI | POLLRDBAND))
 497            {
 498              requested |= FD_OOB;
 499              FD_SET ((SOCKET) h, &xfds);
 500            }
 501
 502          if (requested)
 503            WSAEventSelect ((SOCKET) h, hEvent, requested);
 504        }
 505      else
 506        {
 507          /* Poll now.  If we get an event, do not poll again.  Also,
 508             screen buffer handles are waitable, and they'll block until
 509             a character is available.  win32_compute_revents eliminates
 510             bits for the "wrong" direction. */
 511          pfd[i].revents = win32_compute_revents (h, &sought);
 512          if (sought)
 513            handle_array[nhandles++] = h;
 514          if (pfd[i].revents)
 515            timeout = 0;
 516        }
 517    }
 518
 519  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
 520    {
 521      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
 522         no need to call select again.  */
 523      poll_again = FALSE;
 524      wait_timeout = 0;
 525    }
 526  else
 527    {
 528      poll_again = TRUE;
 529      if (timeout == INFTIM)
 530        wait_timeout = INFINITE;
 531      else
 532        wait_timeout = timeout;
 533    }
 534
 535  for (;;)
 536    {
 537      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
 538                                       wait_timeout, QS_ALLINPUT);
 539
 540      if (ret == WAIT_OBJECT_0 + nhandles)
 541        {
 542          /* new input of some other kind */
 543          BOOL bRet;
 544          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
 545            {
 546              TranslateMessage (&msg);
 547              DispatchMessage (&msg);
 548            }
 549        }
 550      else
 551        break;
 552    }
 553
 554  if (poll_again)
 555    select (0, &rfds, &wfds, &xfds, &tv0);
 556
 557  /* Place a sentinel at the end of the array.  */
 558  handle_array[nhandles] = NULL;
 559  nhandles = 1;
 560  for (i = 0; i < nfd; i++)
 561    {
 562      int happened;
 563
 564      if (pfd[i].fd < 0)
 565        continue;
 566      if (!(pfd[i].events & (POLLIN | POLLRDNORM |
 567                             POLLOUT | POLLWRNORM | POLLWRBAND)))
 568        continue;
 569
 570      h = (HANDLE) _get_osfhandle (pfd[i].fd);
 571      if (h != handle_array[nhandles])
 572        {
 573          /* It's a socket.  */
 574          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
 575          WSAEventSelect ((SOCKET) h, 0, 0);
 576
 577          /* If we're lucky, WSAEnumNetworkEvents already provided a way
 578             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
 579          if (FD_ISSET ((SOCKET) h, &rfds)
 580              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
 581            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
 582          if (FD_ISSET ((SOCKET) h, &wfds))
 583            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
 584          if (FD_ISSET ((SOCKET) h, &xfds))
 585            ev.lNetworkEvents |= FD_OOB;
 586
 587          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
 588                                                   ev.lNetworkEvents);
 589        }
 590      else
 591        {
 592          /* Not a socket.  */
 593          int sought = pfd[i].events;
 594          happened = win32_compute_revents (h, &sought);
 595          nhandles++;
 596        }
 597
 598       if ((pfd[i].revents |= happened) != 0)
 599        rc++;
 600    }
 601
 602  if (!rc && timeout == INFTIM)
 603    {
 604      SwitchToThread();
 605      goto restart;
 606    }
 607
 608  return rc;
 609#endif
 610}