summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/opentracker.c b/opentracker.c
index 34b8fd5..e0f16d7 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -49,7 +49,9 @@ static void panic(const char *routine) {
49 exit(111); 49 exit(111);
50} 50}
51 51
52/* Say we are stopping, wake the loop, and let main do the work on its own stack. */ 52/* Say we are stopping, wake the loop, and let main do the work on its own
53 stack. Everything other than SIGINT falls through and does nothing, which
54 is what OT_SIGNAL_WAKE wants: returning from the read is all it is for. */
53static void signal_handler(int s) { 55static void signal_handler(int s) {
54 if (s == SIGINT) { 56 if (s == SIGINT) {
55 const char byte = 0; 57 const char byte = 0;
@@ -84,8 +86,9 @@ static void install_signal_handlers(void) {
84 86
85 sa.sa_handler = signal_handler; 87 sa.sa_handler = signal_handler;
86 sigemptyset(&sa.sa_mask); 88 sigemptyset(&sa.sa_mask);
87 sa.sa_flags = SA_RESTART; 89 sa.sa_flags = 0;
88 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1)) 90 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1) ||
91 (sigaction(OT_SIGNAL_WAKE, &sa, NULL) == -1))
89 panic("install_signal_handlers"); 92 panic("install_signal_handlers");
90 93
91 sigaddset(&signal_mask, SIGINT); 94 sigaddset(&signal_mask, SIGINT);
@@ -320,8 +323,17 @@ static void *server_mainloop(void *args) {
320} 323}
321 324
322 325
326/* A group of sockets sharing one address only spreads datagrams if every
327 member asked for it before binding, the first one included, so whether
328 this entry will have workers has to be known here. */
329static socket_sharing listen_sharing_for(const ot_listen *entry) {
330 if (entry->proto == FLAG_UDP && entry->workers > 1 && socket_can_balance())
331 return SOCKET_BALANCED;
332 return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE;
333}
334
323static void listen_bind_one(ot_listen *entry) { 335static void listen_bind_one(ot_listen *entry) {
324 socket_sharing sharing = entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; 336 socket_sharing sharing = listen_sharing_for(entry);
325 337
326#ifdef _DEBUG 338#ifdef _DEBUG
327 { 339 {
@@ -370,6 +382,10 @@ static void listen_bind_all(void) {
370 listen_bind_one(entries + i); 382 listen_bind_one(entries + i);
371} 383}
372 384
385/* The socket the event loop was using becomes the first worker's. Where the
386 kernel spreads datagrams, every further worker binds one of its own, so
387 none of them share a receive queue.
388 All others read from the first */
373static void listen_start_udp_workers(void) { 389static void listen_start_udp_workers(void) {
374 size_t count, i; 390 size_t count, i;
375 ot_listen *entries = config_listen_entries(&count); 391 ot_listen *entries = config_listen_entries(&count);
@@ -377,14 +393,28 @@ static void listen_start_udp_workers(void) {
377 udp_init(); 393 udp_init();
378 394
379 for (i = 0; i < count; ++i) { 395 for (i = 0; i < count; ++i) {
380 ot_listen *entry = entries + i; 396 ot_listen *entry = entries + i;
397 int balance = listen_sharing_for(entry) == SOCKET_BALANCED;
398 int worker;
381 399
382 if (entry->proto != FLAG_UDP || entry->workers <= 0) 400 if (entry->proto != FLAG_UDP || entry->workers <= 0)
383 continue; 401 continue;
384 402
385 socket_set_blocking((int)entry->sock, 1);
386 event_del((int)entry->sock); 403 event_del((int)entry->sock);
387 udp_workers_install(entry->sock, (unsigned int)entry->workers); 404 udp_worker_install(entry->sock);
405
406 for (worker = 1; worker < entry->workers; ++worker) {
407 int64_t sock = entry->sock;
408
409 if (balance) {
410 sock = socket_udp_bind(entry->ip, entry->port, SOCKET_BALANCED);
411 if (sock == -1) {
412 fprintf(stderr, "Warning: could not bind another socket for udp worker %d: %s. Sharing the first instead.\n", worker, strerror(errno));
413 sock = entry->sock;
414 }
415 }
416 udp_worker_install(sock);
417 }
388 } 418 }
389} 419}
390 420
@@ -519,9 +549,10 @@ int main(int argc, char **argv) {
519 listen_start_udp_workers(); 549 listen_start_udp_workers();
520 550
521 server_mainloop(0); 551 server_mainloop(0);
552 udp_workers_deinit();
522 553
523 /* The loop has left, so no thread is serving any more and the teardown 554 /* No thread is serving any more, so the teardown can run where a debugger
524 can run where a debugger and the sanitizers can follow it */ 555 and the sanitizers can follow it */
525 trackerlogic_deinit(); 556 trackerlogic_deinit();
526#ifdef WANT_SYSLOGS 557#ifdef WANT_SYSLOGS
527 closelog(); 558 closelog();