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