diff options
Diffstat (limited to 'opentracker.c')
| -rw-r--r-- | opentracker.c | 73 |
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 */ |
| 42 | time_t g_now_seconds; | ||
| 43 | uint32_t g_tracker_id; | 42 | uint32_t g_tracker_id; |
| 44 | volatile int g_opentracker_running = 1; | 43 | _Atomic int g_opentracker_running = 1; |
| 45 | int g_self_pipe[2]; | 44 | int g_self_pipe[2]; |
| 46 | 45 | ||
| 47 | |||
| 48 | static void panic(const char *routine) __attribute__((noreturn)); | 46 | static void panic(const char *routine) __attribute__((noreturn)); |
| 49 | static void panic(const char *routine) { | 47 | static 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. */ | ||
| 54 | static void signal_handler(int s) { | 53 | static 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 | ||
| 211 | static void handle_accept(const int64_t serversocket) { | 208 | static 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 | ||
| 243 | static void *server_mainloop(void *args) { | 239 | static 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. */ |
| 464 | static 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 | |||
| 473 | int main(int argc, char **argv) { | 472 | int 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; |
