summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c73
1 files changed, 38 insertions, 35 deletions
diff --git a/opentracker.c b/opentracker.c
index 11da486..a546fc5 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -39,20 +39,22 @@
39#include "trackerlogic.h" 39#include "trackerlogic.h"
40 40
41/* Globals */ 41/* Globals */
42time_t g_now_seconds;
43uint32_t g_tracker_id; 42uint32_t g_tracker_id;
44volatile int g_opentracker_running = 1; 43_Atomic int g_opentracker_running = 1;
45int g_self_pipe[2]; 44int g_self_pipe[2];
46 45
47
48static void panic(const char *routine) __attribute__((noreturn)); 46static void panic(const char *routine) __attribute__((noreturn));
49static void panic(const char *routine) { 47static void panic(const char *routine) {
50 fprintf(stderr, "%s: %s\n", routine, strerror(errno)); 48 fprintf(stderr, "%s: %s\n", routine, strerror(errno));
51 exit(111); 49 exit(111);
52} 50}
53 51
52/* Say we are stopping, wake the loop, and let main do the work on its own stack. */
54static void signal_handler(int s) { 53static void signal_handler(int s) {
55 if (s == SIGINT) { 54 if (s == SIGINT) {
55 const char byte = 0;
56 int saved = errno;
57
56 /* Any new interrupt signal quits the application */ 58 /* Any new interrupt signal quits the application */
57 signal(SIGINT, SIG_DFL); 59 signal(SIGINT, SIG_DFL);
58 60
@@ -60,13 +62,8 @@ static void signal_handler(int s) {
60 but cancel their operations and return */ 62 but cancel their operations and return */
61 g_opentracker_running = 0; 63 g_opentracker_running = 0;
62 64
63 trackerlogic_deinit(); 65 (void)!write(g_self_pipe[1], &byte, 1);
64 66 errno = saved;
65#ifdef WANT_SYSLOGS
66 closelog();
67#endif
68
69 exit(0);
70 } 67 }
71} 68}
72 69
@@ -87,7 +84,7 @@ static void install_signal_handlers(void) {
87 84
88 sa.sa_handler = signal_handler; 85 sa.sa_handler = signal_handler;
89 sigemptyset(&sa.sa_mask); 86 sigemptyset(&sa.sa_mask);
90 sa.sa_flags = SA_RESTART; 87 sa.sa_flags = 0;
91 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1)) 88 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1))
92 panic("install_signal_handlers"); 89 panic("install_signal_handlers");
93 90
@@ -203,12 +200,12 @@ static void handle_write(const int64_t sock) {
203 waiting to write and go back to waiting for the next request */ 200 waiting to write and go back to waiting for the next request */
204 http_interest_drop(sock, cookie, EVENT_OUT); 201 http_interest_drop(sock, cookie, EVENT_OUT);
205 http_interest_add(sock, cookie, EVENT_IN); 202 http_interest_add(sock, cookie, EVENT_IN);
206 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT); 203 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT));
207 } else 204 } else
208 handle_dead(sock); 205 handle_dead(sock);
209} 206}
210 207
211static void handle_accept(const int64_t serversocket) { 208static void handle_accept(const int64_t serversocket, struct ot_workstruct *ws) {
212 struct http_data *cookie; 209 struct http_data *cookie;
213 int64_t sock; 210 int64_t sock;
214 ot_ip6 ip; 211 ot_ip6 ip;
@@ -218,22 +215,21 @@ static void handle_accept(const int64_t serversocket) {
218 215
219 socket_set_blocking((int)sock, 0); 216 socket_set_blocking((int)sock, 0);
220 217
221 if (!(cookie = (struct http_data *)malloc(sizeof(struct http_data)))) { 218 if (!(cookie = (struct http_data *)calloc(1, sizeof(struct http_data)))) {
222 close((int)sock); 219 close((int)sock);
223 continue; 220 continue;
224 } 221 }
225 memset(cookie, 0, sizeof(struct http_data));
226 memcpy(cookie->ip, ip, sizeof(ot_ip6)); 222 memcpy(cookie->ip, ip, sizeof(ot_ip6));
227 cookie->interest = EVENT_IN; 223 cookie->interest = EVENT_IN;
228 224
229 if (event_add((int)sock, EVENT_IN, fdstate_open(sock, cookie, g_now_seconds + OT_CLIENT_TIMEOUT)) == -1) { 225 if (event_add((int)sock, EVENT_IN, fdstate_open(sock, cookie, time_future_seconds(OT_CLIENT_TIMEOUT))) == -1) {
230 fdstate_close(sock); 226 fdstate_close(sock);
231 free(cookie); 227 free(cookie);
232 close((int)sock); 228 close((int)sock);
233 continue; 229 continue;
234 } 230 }
235 231
236 stats_issue_event(EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip); 232 stats_issue_event(ws, EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
237 } 233 }
238} 234}
239 235
@@ -242,7 +238,7 @@ static void handle_accept(const int64_t serversocket) {
242 238
243static void *server_mainloop(void *args) { 239static void *server_mainloop(void *args) {
244 struct ot_workstruct ws; 240 struct ot_workstruct ws;
245 time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 241 time_t next_timeout_check = time_future_seconds(OT_CLIENT_TIMEOUT_CHECKINTERVAL);
246 struct iovec *iovector; 242 struct iovec *iovector;
247 size_t iovec_entries; 243 size_t iovec_entries;
248 int is_partial; 244 int is_partial;
@@ -250,6 +246,8 @@ static void *server_mainloop(void *args) {
250 (void)args; 246 (void)args;
251 247
252 /* Initialize our "thread local storage" */ 248 /* Initialize our "thread local storage" */
249 memset(&ws, 0, sizeof(ws));
250 stats_counters_register(&ws);
253 ws.inbuf = malloc(G_INBUF_SIZE); 251 ws.inbuf = malloc(G_INBUF_SIZE);
254 ws.outbuf = malloc(G_OUTBUF_SIZE); 252 ws.outbuf = malloc(G_OUTBUF_SIZE);
255#ifdef _DEBUG_HTTPERROR 253#ifdef _DEBUG_HTTPERROR
@@ -261,7 +259,7 @@ static void *server_mainloop(void *args) {
261 259
262 random_bytes(ws.rand48_state, sizeof(ws.rand48_state)); 260 random_bytes(ws.rand48_state, sizeof(ws.rand48_state));
263 261
264 for (;;) { 262 while (g_opentracker_running) {
265 ot_event ready[OT_EVENT_BATCH]; 263 ot_event ready[OT_EVENT_BATCH];
266 int64_t sock; 264 int64_t sock;
267 int count, i; 265 int count, i;
@@ -280,7 +278,7 @@ static void *server_mainloop(void *args) {
280 cookie = fdstate_cookie((int)sock); 278 cookie = fdstate_cookie((int)sock);
281 279
282 if ((intptr_t)cookie == FLAG_TCP) 280 if ((intptr_t)cookie == FLAG_TCP)
283 handle_accept(sock); 281 handle_accept(sock, &ws);
284 else if ((intptr_t)cookie == FLAG_UDP) 282 else if ((intptr_t)cookie == FLAG_UDP)
285 handle_udp6(sock, &ws); 283 handle_udp6(sock, &ws);
286 else if ((intptr_t)cookie == FLAG_SELFPIPE) 284 else if ((intptr_t)cookie == FLAG_SELFPIPE)
@@ -298,16 +296,26 @@ static void *server_mainloop(void *args) {
298 while ((sock = mutex_workqueue_popresult(&iovec_entries, &iovector, &is_partial)) != -1) 296 while ((sock = mutex_workqueue_popresult(&iovec_entries, &iovector, &is_partial)) != -1)
299 http_sendiovecdata(sock, &ws, iovec_entries, iovector, is_partial); 297 http_sendiovecdata(sock, &ws, iovec_entries, iovector, is_partial);
300 298
301 if (g_now_seconds > next_timeout_check) { 299 if (time_now_seconds() > next_timeout_check) {
302 int cursor = 0; 300 int cursor = 0;
303 301
304 while ((sock = fdstate_next_expired(g_now_seconds, &cursor)) != -1) 302 while ((sock = fdstate_next_expired(time_now_seconds(), &cursor)) != -1)
305 handle_dead(sock); 303 handle_dead(sock);
306 next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 304 next_timeout_check = time_future_seconds(OT_CLIENT_TIMEOUT_CHECKINTERVAL);
307 } 305 }
308 306
309 livesync_ticker(); 307 livesync_ticker();
310 } 308 }
309
310 /* This work struct is about to go out of scope, so hand its tally over
311 before anything can read it there */
312 stats_counters_retire(&ws);
313
314 free(ws.inbuf);
315 free(ws.outbuf);
316#ifdef _DEBUG_HTTPERROR
317 free(ws.debugbuf);
318#endif
311 return 0; 319 return 0;
312} 320}
313 321
@@ -461,17 +469,7 @@ int drop_privileges(const char *const serveruser, const char *const serverdir) {
461} 469}
462 470
463/* Maintain our copy of the clock. time() on BSDs is very expensive. */ 471/* Maintain our copy of the clock. time() on BSDs is very expensive. */
464static void *time_caching_worker(void *args) {
465 (void)args;
466 while (1) {
467 g_now_seconds = time(NULL);
468 sleep(5);
469 }
470 return NULL;
471}
472
473int main(int argc, char **argv) { 472int main(int argc, char **argv) {
474 pthread_t thread_id; /* time cacher */
475 473
476 random_init(); 474 random_init();
477 if (fdstate_init() == -1) 475 if (fdstate_init() == -1)
@@ -492,8 +490,6 @@ int main(int argc, char **argv) {
492 if (drop_privileges(g_serveruser ? g_serveruser : "nobody", g_serverdir) == -1) 490 if (drop_privileges(g_serveruser ? g_serveruser : "nobody", g_serverdir) == -1)
493 panic("drop_privileges failed, exiting. Last error"); 491 panic("drop_privileges failed, exiting. Last error");
494 492
495 g_now_seconds = time(NULL);
496 pthread_create(&thread_id, NULL, time_caching_worker, NULL);
497 493
498 /* Create our self pipe which allows us to interrupt mainloops 494 /* Create our self pipe which allows us to interrupt mainloops
499 wait in case some data is available to send out */ 495 wait in case some data is available to send out */
@@ -524,6 +520,13 @@ int main(int argc, char **argv) {
524 520
525 server_mainloop(0); 521 server_mainloop(0);
526 522
523 /* The loop has left, so no thread is serving any more and the teardown
524 can run where a debugger and the sanitizers can follow it */
525 trackerlogic_deinit();
526#ifdef WANT_SYSLOGS
527 closelog();
528#endif
529
527 event_deinit(); 530 event_deinit();
528 fdstate_deinit(); 531 fdstate_deinit();
529 return 0; 532 return 0;