From e704c261cbcbf5448b9bba1c99bcbc33fea8f556 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 18 Aug 2025 16:35:33 -0400 Subject: [PATCH] Use a pipe instead of an eventfd --- src/main.cpp | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ba11aa7..785a680 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,7 @@ #include std::atomic activeConnections{0}; -int shutdown_eventfd = -1; +int shutdown_pipe[2] = {-1, -1}; #ifndef __has_feature #define __has_feature(x) 0 @@ -29,11 +28,11 @@ int shutdown_eventfd = -1; void signal_handler(int sig) { if (sig == SIGTERM || sig == SIGINT) { - if (shutdown_eventfd != -1) { + if (shutdown_pipe[1] != -1) { char val = 1; // write() is async-signal-safe per POSIX - safe to use in signal handler // Write single byte to avoid partial write complexity - while (write(shutdown_eventfd, &val, 1) == -1) { + while (write(shutdown_pipe[1], &val, 1) == -1) { if (errno != EINTR) { abort(); // graceful shutdown didn't work. Let's go ungraceful. } @@ -266,10 +265,15 @@ int main(int argc, char *argv[]) { << config->subscription.keepalive_interval.count() << " seconds" << std::endl; - // Create shutdown eventfd for graceful shutdown - shutdown_eventfd = eventfd(0, EFD_CLOEXEC); - if (shutdown_eventfd == -1) { - perror("eventfd"); + // Create shutdown pipe for graceful shutdown + if (pipe(shutdown_pipe) == -1) { + perror("pipe"); + abort(); + } + // Set both ends to close-on-exec + if (fcntl(shutdown_pipe[0], F_SETFD, FD_CLOEXEC) == -1 || + fcntl(shutdown_pipe[1], F_SETFD, FD_CLOEXEC) == -1) { + perror("fcntl FD_CLOEXEC"); abort(); } @@ -285,11 +289,11 @@ int main(int argc, char *argv[]) { perror("epoll_create"); abort(); } - // Add shutdown eventfd to network thread epoll + // Add shutdown pipe read end to network thread epoll struct epoll_event shutdown_event; shutdown_event.events = EPOLLIN; - shutdown_event.data.fd = shutdown_eventfd; - if (epoll_ctl(network_epollfd, EPOLL_CTL_ADD, shutdown_eventfd, + shutdown_event.data.fd = shutdown_pipe[0]; + if (epoll_ctl(network_epollfd, EPOLL_CTL_ADD, shutdown_pipe[0], &shutdown_event) == -1) { perror("epoll_ctl add shutdown event"); abort(); @@ -323,8 +327,8 @@ int main(int argc, char *argv[]) { for (int i = 0; i < eventCount; ++i) { // Check for shutdown event - if (events[i].data.fd == shutdown_eventfd) { - // Don't read eventfd - all threads need to see shutdown signal + if (events[i].data.fd == shutdown_pipe[0]) { + // Don't read pipe - all threads need to see shutdown signal return; } @@ -383,10 +387,10 @@ int main(int argc, char *argv[]) { abort(); } - // Add shutdown eventfd to accept epoll - if (epoll_ctl(accept_epollfd, EPOLL_CTL_ADD, shutdown_eventfd, + // Add shutdown pipe read end to accept epoll + if (epoll_ctl(accept_epollfd, EPOLL_CTL_ADD, shutdown_pipe[0], &shutdown_event) == -1) { - perror("epoll_ctl shutdown eventfd"); + perror("epoll_ctl shutdown pipe"); abort(); } @@ -409,7 +413,7 @@ int main(int argc, char *argv[]) { ("accept-" + std::to_string(acceptThreadId)).c_str()); for (;;) { - struct epoll_event events[2]; // listen socket + shutdown eventfd + struct epoll_event events[2]; // listen socket + shutdown pipe int ready = epoll_wait(accept_epollfd, events, 2, -1 /* no timeout */); if (ready == -1) { @@ -420,8 +424,8 @@ int main(int argc, char *argv[]) { } for (int i = 0; i < ready; ++i) { - if (events[i].data.fd == shutdown_eventfd) { - // Don't read eventfd - all threads need to see shutdown signal + if (events[i].data.fd == shutdown_pipe[0]) { + // Don't read pipe - all threads need to see shutdown signal return; } @@ -483,7 +487,8 @@ int main(int argc, char *argv[]) { } // Cleanup - close(shutdown_eventfd); + close(shutdown_pipe[0]); + close(shutdown_pipe[1]); close(accept_epollfd); close(network_epollfd); close(sockfd);