diff --git a/src/main.cpp b/src/main.cpp index ddd4b5e..cc49f32 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -301,72 +301,75 @@ int main(int argc, char *argv[]) { int networkThreads = config->server.network_threads; for (int i = 0; i < networkThreads; ++i) { - threads.emplace_back([network_epollfd, i, - max_request_size = - config->server.max_request_size_bytes, - event_batch_size = - config->server.event_batch_size]() { - pthread_setname_np(pthread_self(), - ("network-" + std::to_string(i)).c_str()); - std::vector events(event_batch_size); - for (;;) { - int eventCount = epoll_wait(network_epollfd, events.data(), - event_batch_size, -1 /* no timeout */); - if (eventCount == -1) { - if (errno == EINTR) { - continue; - } - perror("epoll_wait"); - abort(); - } + threads.emplace_back( + [network_epollfd, i, + max_request_size = config->server.max_request_size_bytes, + event_batch_size = config->server.event_batch_size]() { + pthread_setname_np(pthread_self(), + ("network-" + std::to_string(i)).c_str()); + std::vector events(event_batch_size); + for (;;) { + int eventCount = epoll_wait(network_epollfd, events.data(), + event_batch_size, -1 /* no timeout */); + if (eventCount == -1) { + if (errno == EINTR) { + continue; + } + perror("epoll_wait"); + abort(); + } - for (int i = 0; i < eventCount; ++i) { - // Check for shutdown event - if (events[i].data.fd == shutdown_eventfd) { - // Don't read eventfd - all threads need to see shutdown signal - return; - } + for (int i = 0; i < eventCount; ++i) { + // Check for shutdown event + if (events[i].data.fd == shutdown_eventfd) { + // Don't read eventfd - all threads need to see shutdown signal + return; + } - // Take ownership from epoll: raw pointer -> unique_ptr - std::unique_ptr conn{ - static_cast(events[i].data.ptr)}; - conn->tsan_acquire(); - events[i].data.ptr = nullptr; // Clear epoll pointer (we own it now) - const int fd = conn->fd; + // Take ownership from epoll: raw pointer -> unique_ptr + std::unique_ptr conn{ + static_cast(events[i].data.ptr)}; + conn->tsan_acquire(); + events[i].data.ptr = + nullptr; // Clear epoll pointer (we own it now) + const int fd = conn->fd; - if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { - // Connection closed or error occurred - unique_ptr destructor - // cleans up - continue; - } + if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { + // Connection closed or error occurred - unique_ptr destructor + // cleans up + continue; + } - if (events[i].events & EPOLLIN) { - conn->readBytes(max_request_size); - } + if (events[i].events & EPOLLIN) { + conn->readBytes(max_request_size); + } - if (events[i].events & EPOLLOUT) { - bool done = conn->writeBytes(); - if (done) { - continue; + if (events[i].events & EPOLLOUT) { + bool done = conn->writeBytes(); + if (done) { + continue; + } + } + + if (conn->tasks.empty()) { + events[i].events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP; + } else { + events[i].events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP; + } + // Transfer ownership back to epoll: unique_ptr -> raw pointer + conn->tsan_release(); + Connection *raw_conn = + conn.release(); // Get raw pointer before epoll_ctl + events[i].data.ptr = raw_conn; // epoll now owns the connection + int e = epoll_ctl(network_epollfd, EPOLL_CTL_MOD, fd, &events[i]); + if (e == -1) { + perror("epoll_ctl"); + delete raw_conn; // Clean up connection on epoll failure + continue; + } } } - - if (conn->tasks.empty()) { - events[i].events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP; - } else { - events[i].events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP; - } - // Transfer ownership back to epoll: unique_ptr -> raw pointer - conn->tsan_release(); - events[i].data.ptr = conn.release(); // epoll now owns the connection - int e = epoll_ctl(network_epollfd, EPOLL_CTL_MOD, fd, &events[i]); - if (e == -1) { - perror("epoll_ctl"); - abort(); // Connection leaked on abort() is acceptable - OS cleanup - } - } - } - }); + }); } // Accept threads from configuration @@ -454,13 +457,15 @@ int main(int argc, char *argv[]) { struct epoll_event event{}; event.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP; conn->tsan_release(); + Connection *raw_conn = + conn.release(); // Get raw pointer before epoll_ctl event.data.ptr = - conn.release(); // network epoll now owns the connection + raw_conn; // network epoll now owns the connection int e = epoll_ctl(network_epollfd, EPOLL_CTL_ADD, fd, &event); if (e == -1) { perror("epoll_ctl"); - abort(); // Connection leaked on abort() is acceptable - OS - // cleanup + delete raw_conn; // Clean up connection on epoll failure + continue; } } }