Improve some error handling

Handle EINTR in signal handler
Handle getListenFd errors by trying the next address
This commit is contained in:
2025-08-18 15:57:03 -04:00
parent 5bc78577c6
commit 141ae823ab

View File

@@ -30,10 +30,13 @@ int shutdown_eventfd = -1;
void signal_handler(int sig) { void signal_handler(int sig) {
if (sig == SIGTERM || sig == SIGINT) { if (sig == SIGTERM || sig == SIGINT) {
if (shutdown_eventfd != -1) { if (shutdown_eventfd != -1) {
uint64_t val = 1; char val = 1;
// write() is async-signal-safe per POSIX - safe to use in signal handler // write() is async-signal-safe per POSIX - safe to use in signal handler
if (write(shutdown_eventfd, &val, sizeof(val)) == -1) { // Write single byte to avoid partial write complexity
abort(); // Critical failure - can't signal shutdown 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; 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 // Set socket to non-blocking for graceful shutdown
int flags = fcntl(sfd, F_GETFL, 0); int flags = fcntl(sfd, F_GETFL, 0);
if (flags != -1) { if (flags == -1) {
fcntl(sfd, F_SETFL, flags | O_NONBLOCK); 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) { if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) {
@@ -104,13 +118,6 @@ int getListenFd(const char *node, const char *service) {
return sfd; 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 // Since only one thread owns a connection at a time, no synchronization is
// necessary // necessary
// Connection ownership model: // Connection ownership model: