diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-11-01 00:53:53 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-11-01 00:53:53 +0100 |
| commit | af0f2cb1be5aa10bb6a4bdd9f7ef4aa3950ecb31 (patch) | |
| tree | bd366224016709d65bbb0b8fbc3148c29719e8c4 /ot_tcp.c | |
| parent | b7d9dc14eb560b1d19f506610535815f29085579 (diff) | |
Generalize the worker setup/runloop/teardown logic by adding a smol ot_worker helper
Diffstat (limited to 'ot_tcp.c')
| -rw-r--r-- | ot_tcp.c | 66 |
1 files changed, 5 insertions, 61 deletions
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "ot_http.h" | 20 | #include "ot_http.h" |
| 21 | #include "ot_mutex.h" | 21 | #include "ot_mutex.h" |
| 22 | #include "ot_socket.h" | 22 | #include "ot_socket.h" |
| 23 | #include "ot_worker.h" | ||
| 23 | #include "ot_stats.h" | 24 | #include "ot_stats.h" |
| 24 | #include "ot_tcp.h" | 25 | #include "ot_tcp.h" |
| 25 | #include "trackerlogic.h" | 26 | #include "trackerlogic.h" |
| @@ -164,75 +165,18 @@ void tcp_accept(const int64_t serversocket, struct ot_workstruct *ws) { | |||
| 164 | } | 165 | } |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | /* One of these per worker, each allocated on its own so that growing the | ||
| 168 | array below never moves the one a running worker holds. */ | ||
| 169 | struct tcp_worker { | ||
| 170 | pthread_t thread; | ||
| 171 | int64_t sock; | ||
| 172 | _Atomic int left; | ||
| 173 | }; | ||
| 174 | |||
| 175 | static struct tcp_worker **g_workers; | ||
| 176 | static size_t g_worker_count; | ||
| 177 | |||
| 178 | /* A worker blocks in accept and nowhere else: the connection it is handed is | 168 | /* A worker blocks in accept and nowhere else: the connection it is handed is |
| 179 | non blocking, so a client that stops talking is given to the event loop | 169 | non blocking, so a client that stops talking is given to the event loop |
| 180 | rather than keeping this thread. */ | 170 | rather than keeping this thread. */ |
| 181 | static void *tcp_worker(void *args) { | 171 | static void tcp_run(struct ot_worker *me) { |
| 182 | struct tcp_worker *me = args; | ||
| 183 | struct ot_workstruct ws; | ||
| 184 | |||
| 185 | if (workstruct_init(&ws) == -1) { | ||
| 186 | fprintf(stderr, "Warning: a tcp worker could not get its buffers and will not run.\n"); | ||
| 187 | atomic_store(&me->left, 1); | ||
| 188 | return NULL; | ||
| 189 | } | ||
| 190 | |||
| 191 | while (g_opentracker_running) | 172 | while (g_opentracker_running) |
| 192 | tcp_accept(me->sock, &ws); | 173 | tcp_accept(me->sock, &me->ws); |
| 193 | |||
| 194 | workstruct_deinit(&ws); | ||
| 195 | atomic_store(&me->left, 1); | ||
| 196 | return NULL; | ||
| 197 | } | 174 | } |
| 198 | 175 | ||
| 199 | void tcp_worker_install(int64_t sock) { | 176 | void tcp_worker_install(int64_t sock) { |
| 200 | struct tcp_worker **grown = realloc(g_workers, (g_worker_count + 1) * sizeof(*g_workers)); | ||
| 201 | struct tcp_worker *worker; | ||
| 202 | |||
| 203 | if (!grown || !(worker = calloc(1, sizeof(*worker)))) { | ||
| 204 | fprintf(stderr, "Warning: out of memory installing a tcp worker, this socket stays with the workers already running.\n"); | ||
| 205 | g_workers = grown ? grown : g_workers; | ||
| 206 | return; | ||
| 207 | } | ||
| 208 | g_workers = grown; | ||
| 209 | worker->sock = sock; | ||
| 210 | |||
| 211 | socket_set_blocking((int)sock, 1); | 177 | socket_set_blocking((int)sock, 1); |
| 212 | socket_defer_accept((int)sock); | 178 | socket_defer_accept((int)sock); |
| 213 | 179 | ||
| 214 | if (pthread_create(&worker->thread, NULL, tcp_worker, worker)) | 180 | if (worker_start(tcp_run, sock) == -1) |
| 215 | free(worker); | 181 | fprintf(stderr, "Warning: could not install a tcp worker, this socket stays with the workers already running.\n"); |
| 216 | else | ||
| 217 | g_workers[g_worker_count++] = worker; | ||
| 218 | } | ||
| 219 | |||
| 220 | void tcp_workers_deinit(void) { | ||
| 221 | size_t i; | ||
| 222 | |||
| 223 | for (i = 0; i < g_worker_count; ++i) { | ||
| 224 | struct tcp_worker *worker = g_workers[i]; | ||
| 225 | |||
| 226 | /* Repeated because a signal only interrupts a call already under way */ | ||
| 227 | while (!atomic_load(&worker->left)) { | ||
| 228 | pthread_kill(worker->thread, OT_SIGNAL_WAKE); | ||
| 229 | usleep(1000); | ||
| 230 | } | ||
| 231 | pthread_join(worker->thread, NULL); | ||
| 232 | free(worker); | ||
| 233 | } | ||
| 234 | |||
| 235 | free(g_workers); | ||
| 236 | g_workers = NULL; | ||
| 237 | g_worker_count = 0; | ||
| 238 | } | 182 | } |
