Add test for releasing connections back to the server

This commit is contained in:
2025-08-22 13:10:26 -04:00
parent 7860e720bd
commit 1a85e91113
9 changed files with 168 additions and 42 deletions

View File

@@ -42,6 +42,13 @@ Server::Server(const weaseldb::Config &config, ConnectionHandler &handler,
throw std::runtime_error("Failed to set provided listen fd non-blocking");
}
}
// Setup shutdown pipe for graceful shutdown
setup_shutdown_pipe();
// Create epoll instances immediately for createLocalConnection() support
create_epoll_instances();
// If empty vector provided, listen_fds_ will be empty (no listening)
// Server works purely with createLocalConnection()
}
@@ -78,8 +85,7 @@ Server::~Server() {
}
void Server::run() {
setup_shutdown_pipe();
create_epoll_instances();
// Shutdown pipe and epoll instances are now created in constructor
// Create I/O threads locally in this call frame
// CRITICAL: By owning threads in run()'s call frame, we guarantee they are
@@ -140,7 +146,6 @@ void Server::receiveConnectionBack(std::unique_ptr<Connection> connection) {
event.events = EPOLLOUT | EPOLLONESHOT;
}
connection->tsan_release();
int fd = connection->getFd();
event.data.fd = fd;
@@ -159,7 +164,7 @@ void Server::receiveConnectionBack(std::unique_ptr<Connection> connection) {
int Server::createLocalConnection() {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sockets) != 0) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
perror("socketpair");
return -1;
}
@@ -167,6 +172,18 @@ int Server::createLocalConnection() {
int server_fd = sockets[0]; // Server keeps this end
int client_fd = sockets[1]; // Return this end to caller
int flags = fcntl(server_fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl F_GETFL on provided listen fd");
throw std::runtime_error(
"Failed to get flags for server side of local connection");
}
if (fcntl(server_fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl F_SETFL O_NONBLOCK on provided listen fd");
throw std::runtime_error(
"Failed to set server side of local connection to non-blocking");
}
// Create sockaddr_storage for the connection
struct sockaddr_storage addr{};
addr.ss_family = AF_UNIX;
@@ -304,9 +321,7 @@ void Server::start_io_threads(std::vector<std::thread> &threads) {
// Handle existing connection events
int fd = events[i].data.fd;
std::unique_ptr<Connection> conn = connection_registry_.remove(fd);
if (conn) {
conn->tsan_acquire();
}
assert(conn);
if (events[i].events & (EPOLLERR | EPOLLHUP)) {
// unique_ptr will automatically delete on scope exit
@@ -468,7 +483,6 @@ void Server::process_connection_batch(
event.events = EPOLLOUT | EPOLLONESHOT;
}
conn_ptr->tsan_release();
event.data.fd = fd; // Use file descriptor for epoll
// Put connection back in registry since handler didn't take ownership.
// Must happen before epoll_ctl