Mercurial
diff seobeo/os/s_linux_edge.c @ 62:ea9ef388ab97
[Seobeo] Fixed issues with epoll or kqeue in different threads. Initizlied the event looop inside of the thread itself.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 23 Dec 2025 11:48:11 -0800 |
| parents | 84672efec192 |
| children | ecb6ee6a22c3 |
line wrap: on
line diff
--- a/seobeo/os/s_linux_edge.c Sat Dec 20 21:07:34 2025 -0500 +++ b/seobeo/os/s_linux_edge.c Tue Dec 23 11:48:11 2025 -0800 @@ -2,14 +2,34 @@ #include "seobeo/seobeo.h" -void *Seobeo_Web_Edge_Worker(void *vargs) { +void *Seobeo_Web_Edge_Worker(void *vargs) +{ WorkerArgs *args = vargs; 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) { + 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) { + perror("epoll_ctl ADD server"); + close(epfd); + return NULL; + } + while (1) { - int n = epoll_wait(args->evfd, events, max_events, -1); + int n = epoll_wait(epfd, events, max_events, -1); if (n < 0) { + if (errno == EINTR) continue; perror("epoll_wait"); continue; } @@ -18,6 +38,7 @@ Seobeo_PHandle phandle = events[i].data.ptr; if (phandle == args->srv) { + // Accept all pending connections (edge-triggered mode) while (1) { Seobeo_PHandle p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv); if (!p_cli_handle) break; @@ -26,62 +47,54 @@ .events = EPOLLIN | EPOLLET, .data.ptr = p_cli_handle }; - if (epoll_ctl(args->evfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0) + 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); + + // Handle request (this function destroys the handle internally) Seobeo_Web_HandleClientRequest(phandle, args->cache); - epoll_ctl(args->evfd, EPOLL_CTL_DEL, phandle->socket, NULL); - Seobeo_Handle_Destroy(phandle); } } } + close(epfd); return NULL; } void Seobeo_Web_Edge( Seobeo_PHandle p_server_handle, int thread_count, - Dowa_PHashMap p_html_cache) { - - int epfd = epoll_create1(0); - if (epfd < 0) { - perror("epoll_create1"); - return; - } - - struct epoll_event ev = { - .events = EPOLLIN | EPOLLET, - .data.ptr = p_server_handle - }; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_server_handle->socket, &ev) < 0) { - perror("epoll_ctl ADD server"); - close(epfd); - return; - } - + Dowa_PHashMap p_html_cache) +{ pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB + pthread_t threads[thread_count]; for (int i = 0; i < thread_count; i++) { WorkerArgs *args = malloc(sizeof(WorkerArgs)); - *args = (WorkerArgs){ p_server_handle, p_html_cache, epfd }; + *args = (WorkerArgs){ p_server_handle, p_html_cache }; - pthread_t tid; - pthread_create(&tid, &attr, Seobeo_Web_Edge_Worker, args); - pthread_detach(tid); + pthread_create(&threads[i], &attr, Seobeo_Web_Edge_Worker, args); } - while (1) pause(); + // Join threads instead of detaching for proper cleanup + for (int i = 0; i < thread_count; i++) { + pthread_join(threads[i], NULL); + } + + pthread_attr_destroy(&attr); } -void Seobeo_Web_Edge_2(Seobeo_PHandle p_handle_server, Dowa_PHashMap cache) { +void Seobeo_Web_Edge_2(Seobeo_PHandle p_handle_server, Dowa_PHashMap cache) +{ const int MAX_EVENTS = 1024; struct epoll_event events[MAX_EVENTS]; char keybuf[32]; @@ -135,6 +148,7 @@ if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_handle_client->socket, &client_ev) < 0) { perror("epoll_ctl ADD client"); + Seobeo_Handle_Destroy(p_handle_client); continue; } @@ -155,10 +169,18 @@ continue; } + // Remove from epoll + epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); + + // Handle request (this function destroys the handle internally) Seobeo_Web_HandleClientRequest(p_handle_client, cache); + + // Remove from hashmap (handle is already destroyed by HandleClientRequest) + Dowa_HashMap_Pop_Key(handles, keybuf); } } close(epfd); + Dowa_HashMap_Destroy(handles); }