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);
 }