From 141ae823abe33276c84868927d1e2c190024f227 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 18 Aug 2025 15:57:03 -0400 Subject: [PATCH] Improve some error handling Handle EINTR in signal handler Handle getListenFd errors by trying the next address --- src/main.cpp | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d1482aa..ddd4b5e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,10 +30,13 @@ int shutdown_eventfd = -1; void signal_handler(int sig) { if (sig == SIGTERM || sig == SIGINT) { if (shutdown_eventfd != -1) { - uint64_t val = 1; + char val = 1; // write() is async-signal-safe per POSIX - safe to use in signal handler - if (write(shutdown_eventfd, &val, sizeof(val)) == -1) { - abort(); // Critical failure - can't signal shutdown + // Write single byte to avoid partial write complexity + while (write(shutdown_eventfd, &val, 1) == -1) { + if (errno != EINTR) { + abort(); // graceful shutdown didn't work. Let's go ungraceful. + } } } } @@ -73,12 +76,23 @@ int getListenFd(const char *node, const char *service) { } int val = 1; - setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) { + perror("setsockopt SO_REUSEADDR"); + close(sfd); + continue; // Try next address + } // Set socket to non-blocking for graceful shutdown int flags = fcntl(sfd, F_GETFL, 0); - if (flags != -1) { - fcntl(sfd, F_SETFL, flags | O_NONBLOCK); + if (flags == -1) { + perror("fcntl F_GETFL"); + close(sfd); + continue; // Try next address + } + if (fcntl(sfd, F_SETFL, flags | O_NONBLOCK) == -1) { + perror("fcntl F_SETFL"); + close(sfd); + continue; // Try next address } if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { @@ -104,13 +118,6 @@ int getListenFd(const char *node, const char *service) { return sfd; } -int getAcceptFd(int listenFd, struct sockaddr_storage *addr) { - // Use sockaddr_storage (not sockaddr) to handle both IPv4 and IPv6 - socklen_t addrlen = sizeof(sockaddr_storage); - int fd = accept4(listenFd, (struct sockaddr *)addr, &addrlen, SOCK_NONBLOCK); - return fd; -} - // Since only one thread owns a connection at a time, no synchronization is // necessary // Connection ownership model: