Mercurial
comparison seobeo/os/s_macos_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 | c0f6c8c7829f |
| children | ecb6ee6a22c3 |
comparison
equal
deleted
inserted
replaced
| 61:9df5587cf23b | 62:ea9ef388ab97 |
|---|---|
| 4 | 4 |
| 5 void *Seobeo_Web_Edge_Worker(void *vargs) | 5 void *Seobeo_Web_Edge_Worker(void *vargs) |
| 6 { | 6 { |
| 7 WorkerArgs *args = vargs; | 7 WorkerArgs *args = vargs; |
| 8 struct kevent evlist[64]; | 8 struct kevent evlist[64]; |
| 9 | |
| 10 // Each thread creates its own kqueue to avoid race conditions | |
| 11 int kq = kqueue(); | |
| 12 if (kq < 0) { | |
| 13 perror("kqueue"); | |
| 14 return NULL; | |
| 15 } | |
| 16 | |
| 17 // Add server socket to this thread's kqueue | |
| 18 struct kevent kev = { | |
| 19 .ident = args->srv->socket, | |
| 20 .filter = EVFILT_READ, | |
| 21 .flags = EV_ADD, | |
| 22 .udata = args->srv | |
| 23 }; | |
| 24 kevent(kq, &kev, 1, NULL, 0, NULL); | |
| 25 | |
| 9 while (1) | 26 while (1) |
| 10 { | 27 { |
| 11 int ne = kevent(args->evfd, NULL, 0, evlist, 64, NULL); | 28 int ne = kevent(kq, NULL, 0, evlist, 64, NULL); |
| 12 if (ne < 0) continue; | 29 if (ne < 0) { |
| 30 if (errno == EINTR) continue; | |
| 31 perror("kevent"); | |
| 32 continue; | |
| 33 } | |
| 13 | 34 |
| 14 for (int i = 0; i < ne; i++) | 35 for (int i = 0; i < ne; i++) |
| 15 { | 36 { |
| 16 Seobeo_PHandle h = evlist[i].udata; | 37 Seobeo_PHandle h = evlist[i].udata; |
| 17 if (h == args->srv) | 38 if (h == args->srv) |
| 18 { | 39 { |
| 19 Seobeo_PHandle cli = | 40 // Accept new connections in a loop (for edge-triggered behavior) |
| 20 Seobeo_Stream_Handle_Server_Accept(args->srv); | 41 while (1) { |
| 42 Seobeo_PHandle cli = Seobeo_Stream_Handle_Server_Accept(args->srv); | |
| 43 if (!cli) break; | |
| 21 | 44 |
| 22 if (!cli) continue; | 45 struct kevent client_kev = { |
| 23 struct kevent kev = { | 46 .ident = cli->socket, |
| 24 .ident = cli->socket, | 47 .filter = EVFILT_READ, |
| 48 .flags = EV_ADD | EV_ONESHOT, | |
| 49 .udata = cli | |
| 50 }; | |
| 51 kevent(kq, &client_kev, 1, NULL, 0, NULL); | |
| 52 } | |
| 53 } else { | |
| 54 // Remove from kqueue first | |
| 55 struct kevent del_kev = { | |
| 56 .ident = h->socket, | |
| 25 .filter = EVFILT_READ, | 57 .filter = EVFILT_READ, |
| 26 .flags = EV_ADD | EV_ONESHOT, | 58 .flags = EV_DELETE, |
| 27 .udata = cli | |
| 28 }; | 59 }; |
| 29 kevent(args->evfd, &kev, 1, NULL, 0, NULL); | 60 kevent(kq, &del_kev, 1, NULL, 0, NULL); |
| 30 } else { | 61 |
| 31 if (h != args->srv) { | 62 // Handle request (this function destroys the handle internally) |
| 32 struct kevent kev = { | 63 Seobeo_Web_HandleClientRequest(h, args->cache); |
| 33 .ident = h->socket, | |
| 34 .filter = EVFILT_READ, | |
| 35 .flags = EV_DELETE, | |
| 36 }; | |
| 37 kevent(args->evfd, &kev, 1, NULL, 0, NULL); // Remove from kqueue first | |
| 38 | |
| 39 Seobeo_Web_HandleClientRequest(h, args->cache); // this frees | |
| 40 } | |
| 41 } | 64 } |
| 42 } | 65 } |
| 43 } | 66 } |
| 67 | |
| 68 close(kq); | |
| 44 return NULL; | 69 return NULL; |
| 45 } | 70 } |
| 46 | 71 |
| 47 void Seobeo_Web_Edge( | 72 void Seobeo_Web_Edge( |
| 48 Seobeo_PHandle p_server_handle, | 73 Seobeo_PHandle p_server_handle, |
| 49 int thread_count, | 74 int thread_count, |
| 50 Dowa_PHashMap p_html_cache) | 75 Dowa_PHashMap p_html_cache) |
| 51 { | 76 { |
| 52 int kq = kqueue(); | |
| 53 struct kevent kev = { | |
| 54 .ident = p_server_handle->socket, | |
| 55 .filter = EVFILT_READ, | |
| 56 .flags = EV_ADD, | |
| 57 .udata = p_server_handle | |
| 58 }; | |
| 59 kevent(kq, &kev, 1, NULL, 0, NULL); | |
| 60 | |
| 61 pthread_attr_t attr; | 77 pthread_attr_t attr; |
| 62 pthread_attr_init(&attr); | 78 pthread_attr_init(&attr); |
| 63 pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB | 79 pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB |
| 64 | 80 |
| 65 pthread_t threads[thread_count]; | 81 pthread_t threads[thread_count]; |
| 66 for (int i = 0; i < thread_count; i++) | 82 for (int i = 0; i < thread_count; i++) |
| 67 { | 83 { |
| 68 WorkerArgs *args = malloc(sizeof(WorkerArgs)); | 84 WorkerArgs *args = malloc(sizeof(WorkerArgs)); |
| 69 *args = (WorkerArgs){ p_server_handle, p_html_cache, kq }; | 85 *args = (WorkerArgs){ p_server_handle, p_html_cache }; |
| 70 | 86 |
| 71 pthread_create(&threads[i], NULL, Seobeo_Web_Edge_Worker, args); | 87 pthread_create(&threads[i], &attr, Seobeo_Web_Edge_Worker, args); |
| 72 } | 88 } |
| 73 for (int i = 0; i < thread_count; i++) | 89 for (int i = 0; i < thread_count; i++) |
| 74 { | 90 { |
| 75 pthread_join(threads[i], NULL); | 91 pthread_join(threads[i], NULL); |
| 76 } | 92 } |
| 93 | |
| 94 pthread_attr_destroy(&attr); | |
| 77 return; | 95 return; |
| 78 } | 96 } |