Fix EINTR handling for close

This commit is contained in:
2025-08-23 20:14:24 -04:00
parent 7db0e331e4
commit 18a1b30d9f
6 changed files with 86 additions and 78 deletions

View File

@@ -28,14 +28,12 @@ Connection::~Connection() {
if (auto server_ptr = server_.lock()) {
server_ptr->active_connections_.fetch_sub(1, std::memory_order_relaxed);
}
int e;
do {
e = close(fd_);
} while (e == -1 && errno == EINTR);
if (e == -1) {
int e = close(fd_);
if (e == -1 && errno != EINTR) {
perror("close");
std::abort();
}
// EINTR ignored - fd is guaranteed closed on Linux
}
void Connection::appendMessage(std::string_view s, bool copy_to_arena) {

View File

@@ -48,10 +48,6 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
addr.sun_family = AF_UNIX;
if (config.server.unix_socket_path.length() >= sizeof(addr.sun_path)) {
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
std::fprintf(stderr, "Unix socket path too long\n");
std::abort();
}
@@ -61,19 +57,11 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("bind");
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
std::abort();
}
if (listen(sfd, SOMAXCONN) == -1) {
perror("listen");
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
std::abort();
}
@@ -112,10 +100,11 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
int val = 1;
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) {
perror("setsockopt SO_REUSEADDR");
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
int e = close(sfd);
if (e == -1 && errno != EINTR) {
perror("close sfd (SO_REUSEADDR failed)");
std::abort();
}
continue;
}
@@ -123,10 +112,11 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) {
if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) {
perror("setsockopt TCP_NODELAY");
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
int e = close(sfd);
if (e == -1 && errno != EINTR) {
perror("close sfd (TCP_NODELAY failed)");
std::abort();
}
continue;
}
}
@@ -135,10 +125,11 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
break; /* Success */
}
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
int e = close(sfd);
if (e == -1 && errno != EINTR) {
perror("close sfd (bind failed)");
std::abort();
}
sfd = -1;
}
@@ -151,10 +142,6 @@ std::vector<int> create_listen_sockets(const weaseldb::Config &config) {
if (listen(sfd, SOMAXCONN) == -1) {
perror("listen");
int e;
do {
e = close(sfd);
} while (e == -1 && errno == EINTR);
std::abort();
}

View File

@@ -59,27 +59,30 @@ Server::Server(const weaseldb::Config &config, ConnectionHandler &handler,
Server::~Server() {
if (shutdown_pipe_[0] != -1) {
int e;
do {
e = close(shutdown_pipe_[0]);
} while (e == -1 && errno == EINTR);
int e = close(shutdown_pipe_[0]);
if (e == -1 && errno != EINTR) {
perror("close shutdown_pipe_[0]");
std::abort();
}
shutdown_pipe_[0] = -1;
}
if (shutdown_pipe_[1] != -1) {
int e;
do {
e = close(shutdown_pipe_[1]);
} while (e == -1 && errno == EINTR);
int e = close(shutdown_pipe_[1]);
if (e == -1 && errno != EINTR) {
perror("close shutdown_pipe_[1]");
std::abort();
}
shutdown_pipe_[1] = -1;
}
// Close all epoll instances
for (int epollfd : epoll_fds_) {
if (epollfd != -1) {
int e;
do {
e = close(epollfd);
} while (e == -1 && errno == EINTR);
int e = close(epollfd);
if (e == -1 && errno != EINTR) {
perror("close epollfd");
std::abort();
}
}
}
epoll_fds_.clear();
@@ -87,10 +90,11 @@ Server::~Server() {
// Close all listen sockets (Server always owns them)
for (int fd : listen_fds_) {
if (fd != -1) {
int e;
do {
e = close(fd);
} while (e == -1 && errno == EINTR);
int e = close(fd);
if (e == -1 && errno != EINTR) {
perror("close listen_fd");
std::abort();
}
}
}
@@ -226,13 +230,16 @@ int Server::createLocalConnection() {
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, server_fd, &event) == -1) {
perror("epoll_ctl ADD local connection");
connection_registry_.remove(server_fd);
int e;
do {
e = close(server_fd);
} while (e == -1 && errno == EINTR);
do {
e = close(client_fd);
} while (e == -1 && errno == EINTR);
int e = close(server_fd);
if (e == -1 && errno != EINTR) {
perror("close server_fd");
std::abort();
}
e = close(client_fd);
if (e == -1 && errno != EINTR) {
perror("close client_fd");
std::abort();
}
return -1;
}
@@ -384,10 +391,11 @@ void Server::start_io_threads(std::vector<std::thread> &threads) {
if (config_.server.max_connections > 0 &&
active_connections_.load(std::memory_order_relaxed) >=
config_.server.max_connections) {
int e;
do {
e = close(fd);
} while (e == -1 && errno == EINTR);
int e = close(fd);
if (e == -1 && errno != EINTR) {
perror("close fd (max connections)");
std::abort();
}
continue;
}