diff --git a/include/asio/detail/epoll_reactor.hpp b/include/asio/detail/epoll_reactor.hpp index dd05dd5741..e98da8e574 100644 --- a/include/asio/detail/epoll_reactor.hpp +++ b/include/asio/detail/epoll_reactor.hpp @@ -255,6 +255,9 @@ class epoll_reactor // The interrupter is used to break a blocking epoll_wait call. select_interrupter interrupter_; + // The epoll fd set size tracker + int epoll_fd_set_cnt_; + // The epoll file descriptor. int epoll_fd_; diff --git a/include/asio/detail/impl/epoll_reactor.ipp b/include/asio/detail/impl/epoll_reactor.ipp index 1de9a55f52..c07dd286da 100644 --- a/include/asio/detail/impl/epoll_reactor.ipp +++ b/include/asio/detail/impl/epoll_reactor.ipp @@ -42,6 +42,7 @@ epoll_reactor::epoll_reactor(asio::execution_context& ctx) mutex_(config(ctx).get("reactor", "registration_locking", true), config(ctx).get("reactor", "registration_locking_spin_count", 0)), interrupter_(config(ctx).get("reactor", "use_eventfd", true)), + epoll_fd_set_cnt(0), epoll_fd_(do_epoll_create()), timer_fd_(config(ctx).get("reactor", "use_timerfd", true) ? do_timerfd_create() : -1), @@ -67,6 +68,7 @@ epoll_reactor::epoll_reactor(asio::execution_context& ctx) ev.events = EPOLLIN | EPOLLERR; ev.data.ptr = &timer_fd_; epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev); + epoll_fd_set_cnt++; } } @@ -108,6 +110,7 @@ void epoll_reactor::notify_fork( ::close(epoll_fd_); epoll_fd_ = -1; epoll_fd_ = do_epoll_create(); + epoll_fd_set_cnt_ = 0; if (timer_fd_ != -1) { @@ -131,6 +134,7 @@ void epoll_reactor::notify_fork( ev.events = EPOLLIN | EPOLLERR; ev.data.ptr = &timer_fd_; epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev); + epoll_fd_set_cnt_++; } update_timeout(); @@ -146,6 +150,7 @@ void epoll_reactor::notify_fork( ev.data.ptr = state; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev); + epoll_fd_set_cnt++; if (result != 0) { asio::error_code ec(errno, @@ -186,6 +191,7 @@ int epoll_reactor::register_descriptor(socket_type descriptor, descriptor_data->registered_events_ = ev.events; ev.data.ptr = descriptor_data; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + epoll_fd_set_cnt_++; if (result != 0) { if (errno == EPERM) @@ -229,6 +235,7 @@ int epoll_reactor::register_internal_descriptor( descriptor_data->registered_events_ = ev.events; ev.data.ptr = descriptor_data; int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + epoll_fd_set_cnt_++; if (result != 0) { // Don't try to re-register internal descriptor after fork(). @@ -419,6 +426,7 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor, epoll_event ev = { 0, { 0 } }; epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); } + epoll_fd_set_cnt_--; op_queue ops; for (int i = 0; i < max_ops; ++i) @@ -465,6 +473,7 @@ void epoll_reactor::deregister_internal_descriptor(socket_type descriptor, { epoll_event ev = { 0, { 0 } }; epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); + epoll_fd_set_cnt_--; op_queue ops; for (int i = 0; i < max_ops; ++i) @@ -524,7 +533,11 @@ void epoll_reactor::run(long usec, op_queue& ops) // Block on the epoll descriptor. epoll_event events[128]; - int num_events = epoll_wait(epoll_fd_, events, 128, timeout); + int num_events; + if (epoll_fd_set_cnt_ > 0 || timeout) + num_events = epoll_wait(epoll_fd_, events, 128, timeout); + else + num_events = 0; #if defined(ASIO_ENABLE_HANDLER_TRACKING) // Trace the waiting events.