Connection registry

Now we can use leak sanitizer. Yay!
This commit is contained in:
2025-08-21 18:09:36 -04:00
parent 810b5e006d
commit d1b1e6d589
7 changed files with 500 additions and 34 deletions

View File

@@ -0,0 +1,83 @@
#include "connection_registry.hpp"
#include "connection.hpp"
#include <cstring>
#include <stdexcept>
#include <unistd.h>
ConnectionRegistry::ConnectionRegistry() : connections_(nullptr), max_fds_(0) {
// Get the process file descriptor limit
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) {
throw std::runtime_error("Failed to get RLIMIT_NOFILE");
}
max_fds_ = rlim.rlim_cur;
// Allocate virtual address space using mmap
// This reserves virtual memory but doesn't allocate physical pages until
// touched
connections_ = static_cast<Connection **>(
mmap(nullptr, max_fds_ * sizeof(Connection *), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
if (connections_ == MAP_FAILED) {
throw std::runtime_error("Failed to mmap for connection registry");
}
// Initialize all pointers to null
// This will cause physical pages to be allocated on-demand
memset(connections_, 0, max_fds_ * sizeof(Connection *));
}
ConnectionRegistry::~ConnectionRegistry() {
if (connections_ != MAP_FAILED && connections_ != nullptr) {
munmap(connections_, max_fds_ * sizeof(Connection *));
}
}
void ConnectionRegistry::store(int fd, std::unique_ptr<Connection> connection) {
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
return; // Invalid fd - silently ignore to avoid crashes
}
// Release ownership from unique_ptr and store raw pointer
connections_[fd] = connection.release();
}
bool ConnectionRegistry::has(int fd) const {
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
return false; // Invalid fd
}
return connections_[fd] != nullptr;
}
std::unique_ptr<Connection> ConnectionRegistry::remove(int fd) {
if (fd < 0 || static_cast<size_t>(fd) >= max_fds_) {
return nullptr; // Invalid fd
}
Connection *conn = connections_[fd];
connections_[fd] = nullptr;
// Transfer ownership back to unique_ptr
return std::unique_ptr<Connection>(conn);
}
void ConnectionRegistry::shutdown_cleanup() {
// Iterate through all possible file descriptors and clean up any connections
// Following the critical ordering: remove -> delete (destructor handles
// close)
size_t connections_found = 0;
for (size_t fd = 0; fd < max_fds_; ++fd) {
Connection *conn = connections_[fd];
if (conn != nullptr) {
connections_found++;
// Step 1: Remove from registry (set to null)
connections_[fd] = nullptr;
// Steps 2 & 3: Delete the connection object (destructor handles closing
// fd)
delete conn;
}
}
// Note: In normal shutdown, this should be 0 since all connections
// should have been properly cleaned up during normal operation
}