Mercurial
diff seobeo/os/s_linux_edge.c @ 183:a8976a008a9d
[BenchMark] Added bun bench mark to test seoboe vs other popular benchmarks.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 23 Jan 2026 21:19:08 -0800 |
| parents | 48f260576059 |
| children |
line wrap: on
line diff
--- a/seobeo/os/s_linux_edge.c Thu Jan 22 21:23:17 2026 -0800 +++ b/seobeo/os/s_linux_edge.c Fri Jan 23 21:19:08 2026 -0800 @@ -1,6 +1,27 @@ #include <sys/epoll.h> +#include <netinet/tcp.h> #include "seobeo/seobeo.h" +// TCP keep-alive settings +#define KEEP_ALIVE_IDLE_SEC 30 // Start probes after 30s idle +#define KEEP_ALIVE_INTERVAL 5 // Probe every 5 seconds +#define KEEP_ALIVE_COUNT 3 // Close after 3 failed probes + +// Configure TCP keep-alive on socket (kernel handles timeout) +static void configure_keep_alive(int socket) +{ + int enable = 1; + setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + + int idle = KEEP_ALIVE_IDLE_SEC; + setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle)); + + int interval = KEEP_ALIVE_INTERVAL; + setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)); + + int count = KEEP_ALIVE_COUNT; + setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(count)); +} void *Seobeo_Web_Edge_Worker(void *vargs) { @@ -8,57 +29,93 @@ const int max_events = 64; struct epoll_event events[max_events]; - // Each thread creates its own epoll to avoid race conditions int epfd = epoll_create1(0); - if (epfd < 0) { + if (epfd < 0) + { perror("epoll_create1"); return NULL; } - // Add server socket to this thread's epoll struct epoll_event ev = { .events = EPOLLIN | EPOLLET, .data.ptr = args->srv }; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0) { + if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0) + { perror("epoll_ctl ADD server"); close(epfd); return NULL; } - while (1) { - int n = epoll_wait(epfd, events, max_events, -1); - if (n < 0) { - if (errno == EINTR) continue; + while (1) + { + int n = epoll_wait(epfd, events, max_events, -1); // Block indefinitely, kernel handles timeouts + if (n < 0) + { + if (errno == EINTR) + continue; perror("epoll_wait"); continue; } - for (int i = 0; i < n; i++) { - Seobeo_Handle *phandle = events[i].data.ptr; + for (int i = 0; i < n; i++) + { + Seobeo_Handle *p_handle = events[i].data.ptr; - if (phandle == args->srv) { - // Accept all pending connections (edge-triggered mode) - while (1) { + // Server socket - accept new connections + if (p_handle == args->srv) + { + while (1) + { Seobeo_Handle *p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv); if (!p_cli_handle) break; + // Let kernel handle keep-alive timeout + configure_keep_alive(p_cli_handle->socket); + struct epoll_event client_ev = { .events = EPOLLIN | EPOLLET, .data.ptr = p_cli_handle }; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0) { perror("epoll_ctl ADD client"); Seobeo_Handle_Destroy(p_cli_handle); } } - } else { - // Remove from epoll first - epoll_ctl(epfd, EPOLL_CTL_DEL, phandle->socket, NULL); + } + // Client socket - handle request + else + { + Seobeo_Handle *p_client_handle = p_handle; + + // Connection error or hangup - clean up + if (events[i].events & (EPOLLERR | EPOLLHUP)) + { + epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL); + Seobeo_Handle_Destroy(p_client_handle); + continue; + } - // Handle request (this function destroys the handle internally) - Seobeo_Web_HandleClientRequest(phandle, args->cache); + // Handle requests (loop for pipelined requests) + boolean keep_alive = TRUE; + while (keep_alive) + { + keep_alive = Seobeo_Web_ClientHandle_Request(p_client_handle, args->cache, TRUE); + + // No more data in buffer, wait for next epoll event + if (keep_alive && p_client_handle->read_buffer_len == 0) + break; + } + + // Client wants to close + if (!keep_alive) + { + epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL); + Seobeo_Handle_Destroy(p_client_handle); + } + // Connection stays open, kernel will timeout if idle } } }