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) {
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: