11cb0ef41Sopenharmony_ci/* Copyright libuv contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "uv.h"
231cb0ef41Sopenharmony_ci#include "internal.h"
241cb0ef41Sopenharmony_ci#include <errno.h>
251cb0ef41Sopenharmony_ci#include <sys/epoll.h>
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciint uv__epoll_init(uv_loop_t* loop) {
281cb0ef41Sopenharmony_ci  int fd;
291cb0ef41Sopenharmony_ci  fd = epoll_create1(O_CLOEXEC);
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  /* epoll_create1() can fail either because it's not implemented (old kernel)
321cb0ef41Sopenharmony_ci   * or because it doesn't understand the O_CLOEXEC flag.
331cb0ef41Sopenharmony_ci   */
341cb0ef41Sopenharmony_ci  if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
351cb0ef41Sopenharmony_ci    fd = epoll_create(256);
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci    if (fd != -1)
381cb0ef41Sopenharmony_ci      uv__cloexec(fd, 1);
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  loop->backend_fd = fd;
421cb0ef41Sopenharmony_ci  if (fd == -1)
431cb0ef41Sopenharmony_ci    return UV__ERR(errno);
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  return 0;
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_civoid uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
501cb0ef41Sopenharmony_ci  struct epoll_event* events;
511cb0ef41Sopenharmony_ci  struct epoll_event dummy;
521cb0ef41Sopenharmony_ci  uintptr_t i;
531cb0ef41Sopenharmony_ci  uintptr_t nfds;
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  assert(loop->watchers != NULL);
561cb0ef41Sopenharmony_ci  assert(fd >= 0);
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  events = (struct epoll_event*) loop->watchers[loop->nwatchers];
591cb0ef41Sopenharmony_ci  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
601cb0ef41Sopenharmony_ci  if (events != NULL)
611cb0ef41Sopenharmony_ci    /* Invalidate events with same file descriptor */
621cb0ef41Sopenharmony_ci    for (i = 0; i < nfds; i++)
631cb0ef41Sopenharmony_ci      if (events[i].data.fd == fd)
641cb0ef41Sopenharmony_ci        events[i].data.fd = -1;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  /* Remove the file descriptor from the epoll.
671cb0ef41Sopenharmony_ci   * This avoids a problem where the same file description remains open
681cb0ef41Sopenharmony_ci   * in another process, causing repeated junk epoll events.
691cb0ef41Sopenharmony_ci   *
701cb0ef41Sopenharmony_ci   * We pass in a dummy epoll_event, to work around a bug in old kernels.
711cb0ef41Sopenharmony_ci   */
721cb0ef41Sopenharmony_ci  if (loop->backend_fd >= 0) {
731cb0ef41Sopenharmony_ci    /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
741cb0ef41Sopenharmony_ci     * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
751cb0ef41Sopenharmony_ci     */
761cb0ef41Sopenharmony_ci    memset(&dummy, 0, sizeof(dummy));
771cb0ef41Sopenharmony_ci    epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
781cb0ef41Sopenharmony_ci  }
791cb0ef41Sopenharmony_ci}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ciint uv__io_check_fd(uv_loop_t* loop, int fd) {
831cb0ef41Sopenharmony_ci  struct epoll_event e;
841cb0ef41Sopenharmony_ci  int rc;
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  memset(&e, 0, sizeof(e));
871cb0ef41Sopenharmony_ci  e.events = POLLIN;
881cb0ef41Sopenharmony_ci  e.data.fd = -1;
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  rc = 0;
911cb0ef41Sopenharmony_ci  if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
921cb0ef41Sopenharmony_ci    if (errno != EEXIST)
931cb0ef41Sopenharmony_ci      rc = UV__ERR(errno);
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  if (rc == 0)
961cb0ef41Sopenharmony_ci    if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
971cb0ef41Sopenharmony_ci      abort();
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  return rc;
1001cb0ef41Sopenharmony_ci}
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_civoid uv__io_poll(uv_loop_t* loop, int timeout) {
1041cb0ef41Sopenharmony_ci  /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
1051cb0ef41Sopenharmony_ci   * effectively infinite on 32 bits architectures.  To avoid blocking
1061cb0ef41Sopenharmony_ci   * indefinitely, we cap the timeout and poll again if necessary.
1071cb0ef41Sopenharmony_ci   *
1081cb0ef41Sopenharmony_ci   * Note that "30 minutes" is a simplification because it depends on
1091cb0ef41Sopenharmony_ci   * the value of CONFIG_HZ.  The magic constant assumes CONFIG_HZ=1200,
1101cb0ef41Sopenharmony_ci   * that being the largest value I have seen in the wild (and only once.)
1111cb0ef41Sopenharmony_ci   */
1121cb0ef41Sopenharmony_ci  static const int max_safe_timeout = 1789569;
1131cb0ef41Sopenharmony_ci  static int no_epoll_pwait_cached;
1141cb0ef41Sopenharmony_ci  static int no_epoll_wait_cached;
1151cb0ef41Sopenharmony_ci  int no_epoll_pwait;
1161cb0ef41Sopenharmony_ci  int no_epoll_wait;
1171cb0ef41Sopenharmony_ci  struct epoll_event events[1024];
1181cb0ef41Sopenharmony_ci  struct epoll_event* pe;
1191cb0ef41Sopenharmony_ci  struct epoll_event e;
1201cb0ef41Sopenharmony_ci  int real_timeout;
1211cb0ef41Sopenharmony_ci  QUEUE* q;
1221cb0ef41Sopenharmony_ci  uv__io_t* w;
1231cb0ef41Sopenharmony_ci  sigset_t sigset;
1241cb0ef41Sopenharmony_ci  uint64_t sigmask;
1251cb0ef41Sopenharmony_ci  uint64_t base;
1261cb0ef41Sopenharmony_ci  int have_signals;
1271cb0ef41Sopenharmony_ci  int nevents;
1281cb0ef41Sopenharmony_ci  int count;
1291cb0ef41Sopenharmony_ci  int nfds;
1301cb0ef41Sopenharmony_ci  int fd;
1311cb0ef41Sopenharmony_ci  int op;
1321cb0ef41Sopenharmony_ci  int i;
1331cb0ef41Sopenharmony_ci  int user_timeout;
1341cb0ef41Sopenharmony_ci  int reset_timeout;
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  if (loop->nfds == 0) {
1371cb0ef41Sopenharmony_ci    assert(QUEUE_EMPTY(&loop->watcher_queue));
1381cb0ef41Sopenharmony_ci    return;
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  memset(&e, 0, sizeof(e));
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
1441cb0ef41Sopenharmony_ci    q = QUEUE_HEAD(&loop->watcher_queue);
1451cb0ef41Sopenharmony_ci    QUEUE_REMOVE(q);
1461cb0ef41Sopenharmony_ci    QUEUE_INIT(q);
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
1491cb0ef41Sopenharmony_ci    assert(w->pevents != 0);
1501cb0ef41Sopenharmony_ci    assert(w->fd >= 0);
1511cb0ef41Sopenharmony_ci    assert(w->fd < (int) loop->nwatchers);
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci    e.events = w->pevents;
1541cb0ef41Sopenharmony_ci    e.data.fd = w->fd;
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci    if (w->events == 0)
1571cb0ef41Sopenharmony_ci      op = EPOLL_CTL_ADD;
1581cb0ef41Sopenharmony_ci    else
1591cb0ef41Sopenharmony_ci      op = EPOLL_CTL_MOD;
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci    /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
1621cb0ef41Sopenharmony_ci     * events, skip the syscall and squelch the events after epoll_wait().
1631cb0ef41Sopenharmony_ci     */
1641cb0ef41Sopenharmony_ci    if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
1651cb0ef41Sopenharmony_ci      if (errno != EEXIST)
1661cb0ef41Sopenharmony_ci        abort();
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci      assert(op == EPOLL_CTL_ADD);
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci      /* We've reactivated a file descriptor that's been watched before. */
1711cb0ef41Sopenharmony_ci      if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
1721cb0ef41Sopenharmony_ci        abort();
1731cb0ef41Sopenharmony_ci    }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    w->events = w->pevents;
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  sigmask = 0;
1791cb0ef41Sopenharmony_ci  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
1801cb0ef41Sopenharmony_ci    sigemptyset(&sigset);
1811cb0ef41Sopenharmony_ci    sigaddset(&sigset, SIGPROF);
1821cb0ef41Sopenharmony_ci    sigmask |= 1 << (SIGPROF - 1);
1831cb0ef41Sopenharmony_ci  }
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  assert(timeout >= -1);
1861cb0ef41Sopenharmony_ci  base = loop->time;
1871cb0ef41Sopenharmony_ci  count = 48; /* Benchmarks suggest this gives the best throughput. */
1881cb0ef41Sopenharmony_ci  real_timeout = timeout;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) {
1911cb0ef41Sopenharmony_ci    reset_timeout = 1;
1921cb0ef41Sopenharmony_ci    user_timeout = timeout;
1931cb0ef41Sopenharmony_ci    timeout = 0;
1941cb0ef41Sopenharmony_ci  } else {
1951cb0ef41Sopenharmony_ci    reset_timeout = 0;
1961cb0ef41Sopenharmony_ci    user_timeout = 0;
1971cb0ef41Sopenharmony_ci  }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  /* You could argue there is a dependency between these two but
2001cb0ef41Sopenharmony_ci   * ultimately we don't care about their ordering with respect
2011cb0ef41Sopenharmony_ci   * to one another. Worst case, we make a few system calls that
2021cb0ef41Sopenharmony_ci   * could have been avoided because another thread already knows
2031cb0ef41Sopenharmony_ci   * they fail with ENOSYS. Hardly the end of the world.
2041cb0ef41Sopenharmony_ci   */
2051cb0ef41Sopenharmony_ci  no_epoll_pwait = uv__load_relaxed(&no_epoll_pwait_cached);
2061cb0ef41Sopenharmony_ci  no_epoll_wait = uv__load_relaxed(&no_epoll_wait_cached);
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  for (;;) {
2091cb0ef41Sopenharmony_ci    /* Only need to set the provider_entry_time if timeout != 0. The function
2101cb0ef41Sopenharmony_ci     * will return early if the loop isn't configured with UV_METRICS_IDLE_TIME.
2111cb0ef41Sopenharmony_ci     */
2121cb0ef41Sopenharmony_ci    if (timeout != 0)
2131cb0ef41Sopenharmony_ci      uv__metrics_set_provider_entry_time(loop);
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci    /* See the comment for max_safe_timeout for an explanation of why
2161cb0ef41Sopenharmony_ci     * this is necessary.  Executive summary: kernel bug workaround.
2171cb0ef41Sopenharmony_ci     */
2181cb0ef41Sopenharmony_ci    if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
2191cb0ef41Sopenharmony_ci      timeout = max_safe_timeout;
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci    if (sigmask != 0 && no_epoll_pwait != 0)
2221cb0ef41Sopenharmony_ci      if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
2231cb0ef41Sopenharmony_ci        abort();
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci    if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
2261cb0ef41Sopenharmony_ci      nfds = epoll_pwait(loop->backend_fd,
2271cb0ef41Sopenharmony_ci                         events,
2281cb0ef41Sopenharmony_ci                         ARRAY_SIZE(events),
2291cb0ef41Sopenharmony_ci                         timeout,
2301cb0ef41Sopenharmony_ci                         &sigset);
2311cb0ef41Sopenharmony_ci      if (nfds == -1 && errno == ENOSYS) {
2321cb0ef41Sopenharmony_ci        uv__store_relaxed(&no_epoll_pwait_cached, 1);
2331cb0ef41Sopenharmony_ci        no_epoll_pwait = 1;
2341cb0ef41Sopenharmony_ci      }
2351cb0ef41Sopenharmony_ci    } else {
2361cb0ef41Sopenharmony_ci      nfds = epoll_wait(loop->backend_fd,
2371cb0ef41Sopenharmony_ci                        events,
2381cb0ef41Sopenharmony_ci                        ARRAY_SIZE(events),
2391cb0ef41Sopenharmony_ci                        timeout);
2401cb0ef41Sopenharmony_ci      if (nfds == -1 && errno == ENOSYS) {
2411cb0ef41Sopenharmony_ci        uv__store_relaxed(&no_epoll_wait_cached, 1);
2421cb0ef41Sopenharmony_ci        no_epoll_wait = 1;
2431cb0ef41Sopenharmony_ci      }
2441cb0ef41Sopenharmony_ci    }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    if (sigmask != 0 && no_epoll_pwait != 0)
2471cb0ef41Sopenharmony_ci      if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
2481cb0ef41Sopenharmony_ci        abort();
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci    /* Update loop->time unconditionally. It's tempting to skip the update when
2511cb0ef41Sopenharmony_ci     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
2521cb0ef41Sopenharmony_ci     * operating system didn't reschedule our process while in the syscall.
2531cb0ef41Sopenharmony_ci     */
2541cb0ef41Sopenharmony_ci    SAVE_ERRNO(uv__update_time(loop));
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    if (nfds == 0) {
2571cb0ef41Sopenharmony_ci      assert(timeout != -1);
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci      if (reset_timeout != 0) {
2601cb0ef41Sopenharmony_ci        timeout = user_timeout;
2611cb0ef41Sopenharmony_ci        reset_timeout = 0;
2621cb0ef41Sopenharmony_ci      }
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci      if (timeout == -1)
2651cb0ef41Sopenharmony_ci        continue;
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci      if (timeout == 0)
2681cb0ef41Sopenharmony_ci        return;
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci      /* We may have been inside the system call for longer than |timeout|
2711cb0ef41Sopenharmony_ci       * milliseconds so we need to update the timestamp to avoid drift.
2721cb0ef41Sopenharmony_ci       */
2731cb0ef41Sopenharmony_ci      goto update_timeout;
2741cb0ef41Sopenharmony_ci    }
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci    if (nfds == -1) {
2771cb0ef41Sopenharmony_ci      if (errno == ENOSYS) {
2781cb0ef41Sopenharmony_ci        /* epoll_wait() or epoll_pwait() failed, try the other system call. */
2791cb0ef41Sopenharmony_ci        assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
2801cb0ef41Sopenharmony_ci        continue;
2811cb0ef41Sopenharmony_ci      }
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci      if (errno != EINTR)
2841cb0ef41Sopenharmony_ci        abort();
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci      if (reset_timeout != 0) {
2871cb0ef41Sopenharmony_ci        timeout = user_timeout;
2881cb0ef41Sopenharmony_ci        reset_timeout = 0;
2891cb0ef41Sopenharmony_ci      }
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci      if (timeout == -1)
2921cb0ef41Sopenharmony_ci        continue;
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci      if (timeout == 0)
2951cb0ef41Sopenharmony_ci        return;
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci      /* Interrupted by a signal. Update timeout and poll again. */
2981cb0ef41Sopenharmony_ci      goto update_timeout;
2991cb0ef41Sopenharmony_ci    }
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci    have_signals = 0;
3021cb0ef41Sopenharmony_ci    nevents = 0;
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci    {
3051cb0ef41Sopenharmony_ci      /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
3061cb0ef41Sopenharmony_ci      union {
3071cb0ef41Sopenharmony_ci        struct epoll_event* events;
3081cb0ef41Sopenharmony_ci        uv__io_t* watchers;
3091cb0ef41Sopenharmony_ci      } x;
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci      x.events = events;
3121cb0ef41Sopenharmony_ci      assert(loop->watchers != NULL);
3131cb0ef41Sopenharmony_ci      loop->watchers[loop->nwatchers] = x.watchers;
3141cb0ef41Sopenharmony_ci      loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
3151cb0ef41Sopenharmony_ci    }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    for (i = 0; i < nfds; i++) {
3181cb0ef41Sopenharmony_ci      pe = events + i;
3191cb0ef41Sopenharmony_ci      fd = pe->data.fd;
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci      /* Skip invalidated events, see uv__platform_invalidate_fd */
3221cb0ef41Sopenharmony_ci      if (fd == -1)
3231cb0ef41Sopenharmony_ci        continue;
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci      assert(fd >= 0);
3261cb0ef41Sopenharmony_ci      assert((unsigned) fd < loop->nwatchers);
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci      w = loop->watchers[fd];
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci      if (w == NULL) {
3311cb0ef41Sopenharmony_ci        /* File descriptor that we've stopped watching, disarm it.
3321cb0ef41Sopenharmony_ci         *
3331cb0ef41Sopenharmony_ci         * Ignore all errors because we may be racing with another thread
3341cb0ef41Sopenharmony_ci         * when the file descriptor is closed.
3351cb0ef41Sopenharmony_ci         */
3361cb0ef41Sopenharmony_ci        epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
3371cb0ef41Sopenharmony_ci        continue;
3381cb0ef41Sopenharmony_ci      }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci      /* Give users only events they're interested in. Prevents spurious
3411cb0ef41Sopenharmony_ci       * callbacks when previous callback invocation in this loop has stopped
3421cb0ef41Sopenharmony_ci       * the current watcher. Also, filters out events that users has not
3431cb0ef41Sopenharmony_ci       * requested us to watch.
3441cb0ef41Sopenharmony_ci       */
3451cb0ef41Sopenharmony_ci      pe->events &= w->pevents | POLLERR | POLLHUP;
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci      /* Work around an epoll quirk where it sometimes reports just the
3481cb0ef41Sopenharmony_ci       * EPOLLERR or EPOLLHUP event.  In order to force the event loop to
3491cb0ef41Sopenharmony_ci       * move forward, we merge in the read/write events that the watcher
3501cb0ef41Sopenharmony_ci       * is interested in; uv__read() and uv__write() will then deal with
3511cb0ef41Sopenharmony_ci       * the error or hangup in the usual fashion.
3521cb0ef41Sopenharmony_ci       *
3531cb0ef41Sopenharmony_ci       * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
3541cb0ef41Sopenharmony_ci       * reads the available data, calls uv_read_stop(), then sometime later
3551cb0ef41Sopenharmony_ci       * calls uv_read_start() again.  By then, libuv has forgotten about the
3561cb0ef41Sopenharmony_ci       * hangup and the kernel won't report EPOLLIN again because there's
3571cb0ef41Sopenharmony_ci       * nothing left to read.  If anything, libuv is to blame here.  The
3581cb0ef41Sopenharmony_ci       * current hack is just a quick bandaid; to properly fix it, libuv
3591cb0ef41Sopenharmony_ci       * needs to remember the error/hangup event.  We should get that for
3601cb0ef41Sopenharmony_ci       * free when we switch over to edge-triggered I/O.
3611cb0ef41Sopenharmony_ci       */
3621cb0ef41Sopenharmony_ci      if (pe->events == POLLERR || pe->events == POLLHUP)
3631cb0ef41Sopenharmony_ci        pe->events |=
3641cb0ef41Sopenharmony_ci          w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci      if (pe->events != 0) {
3671cb0ef41Sopenharmony_ci        /* Run signal watchers last.  This also affects child process watchers
3681cb0ef41Sopenharmony_ci         * because those are implemented in terms of signal watchers.
3691cb0ef41Sopenharmony_ci         */
3701cb0ef41Sopenharmony_ci        if (w == &loop->signal_io_watcher) {
3711cb0ef41Sopenharmony_ci          have_signals = 1;
3721cb0ef41Sopenharmony_ci        } else {
3731cb0ef41Sopenharmony_ci          uv__metrics_update_idle_time(loop);
3741cb0ef41Sopenharmony_ci          w->cb(loop, w, pe->events);
3751cb0ef41Sopenharmony_ci        }
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci        nevents++;
3781cb0ef41Sopenharmony_ci      }
3791cb0ef41Sopenharmony_ci    }
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci    if (reset_timeout != 0) {
3821cb0ef41Sopenharmony_ci      timeout = user_timeout;
3831cb0ef41Sopenharmony_ci      reset_timeout = 0;
3841cb0ef41Sopenharmony_ci    }
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci    if (have_signals != 0) {
3871cb0ef41Sopenharmony_ci      uv__metrics_update_idle_time(loop);
3881cb0ef41Sopenharmony_ci      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
3891cb0ef41Sopenharmony_ci    }
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci    loop->watchers[loop->nwatchers] = NULL;
3921cb0ef41Sopenharmony_ci    loop->watchers[loop->nwatchers + 1] = NULL;
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci    if (have_signals != 0)
3951cb0ef41Sopenharmony_ci      return;  /* Event loop should cycle now so don't poll again. */
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci    if (nevents != 0) {
3981cb0ef41Sopenharmony_ci      if (nfds == ARRAY_SIZE(events) && --count != 0) {
3991cb0ef41Sopenharmony_ci        /* Poll for more events but don't block this time. */
4001cb0ef41Sopenharmony_ci        timeout = 0;
4011cb0ef41Sopenharmony_ci        continue;
4021cb0ef41Sopenharmony_ci      }
4031cb0ef41Sopenharmony_ci      return;
4041cb0ef41Sopenharmony_ci    }
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci    if (timeout == 0)
4071cb0ef41Sopenharmony_ci      return;
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci    if (timeout == -1)
4101cb0ef41Sopenharmony_ci      continue;
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ciupdate_timeout:
4131cb0ef41Sopenharmony_ci    assert(timeout > 0);
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci    real_timeout -= (loop->time - base);
4161cb0ef41Sopenharmony_ci    if (real_timeout <= 0)
4171cb0ef41Sopenharmony_ci      return;
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci    timeout = real_timeout;
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci}
4221cb0ef41Sopenharmony_ci
423