Improve some error handling
Handle EINTR in signal handler Handle getListenFd errors by trying the next address
This commit is contained in:
33
src/main.cpp
33
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:
|
||||
|
||||
Reference in New Issue
Block a user