diff options
Diffstat (limited to 'ot_accesslist.c')
| -rw-r--r-- | ot_accesslist.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/ot_accesslist.c b/ot_accesslist.c index e8e0476..df084b8 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c | |||
| @@ -273,7 +273,8 @@ static void *accesslist_worker(void *args) { | |||
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | #ifdef WANT_DYNAMIC_ACCESSLIST | 275 | #ifdef WANT_DYNAMIC_ACCESSLIST |
| 276 | static pthread_t thread_adder_id, thread_deleter_id; | 276 | static pthread_t thread_adder_id, thread_deleter_id; |
| 277 | static _Atomic int adder_left, deleter_left; | ||
| 277 | static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_Atomic *adding_to, ot_accesslist *_Atomic *removing_from) { | 278 | static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_Atomic *adding_to, ot_accesslist *_Atomic *removing_from) { |
| 278 | struct stat st; | 279 | struct stat st; |
| 279 | 280 | ||
| @@ -297,6 +298,9 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 297 | ssize_t linelen; | 298 | ssize_t linelen; |
| 298 | 299 | ||
| 299 | if (!fifo) { | 300 | if (!fifo) { |
| 301 | /* Woken on purpose: the loop condition above decides what happens next */ | ||
| 302 | if (errno == EINTR) | ||
| 303 | continue; | ||
| 300 | fprintf(stderr, "Error when reading dynamic accesslists: Couldn't open FIFO at %s, error: %s\n", fifoname, strerror(errno)); | 304 | fprintf(stderr, "Error when reading dynamic accesslists: Couldn't open FIFO at %s, error: %s\n", fifoname, strerror(errno)); |
| 301 | return NULL; | 305 | return NULL; |
| 302 | } | 306 | } |
| @@ -324,8 +328,14 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 324 | ptrdiff_t off = exactmatch - (*removing_from)->list; | 328 | ptrdiff_t off = exactmatch - (*removing_from)->list; |
| 325 | ot_accesslist *accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1); | 329 | ot_accesslist *accesslist_new = accesslist_make(*removing_from, (*removing_from)->size - 1); |
| 326 | if (accesslist_new) { | 330 | if (accesslist_new) { |
| 327 | memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); | 331 | size_t after = (*removing_from)->size - off - 1; |
| 328 | memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * ((*removing_from)->size - off - 1)); | 332 | |
| 333 | /* Removing the only entry leaves a list with no room at all, and | ||
| 334 | memcpy may not be handed that even for nothing */ | ||
| 335 | if (off) | ||
| 336 | memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); | ||
| 337 | if (after) | ||
| 338 | memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * after); | ||
| 329 | (*removing_from)->base = time_now_minutes(); | 339 | (*removing_from)->base = time_now_minutes(); |
| 330 | *removing_from = accesslist_new; | 340 | *removing_from = accesslist_new; |
| 331 | } | 341 | } |
| @@ -360,6 +370,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 360 | pthread_mutex_unlock(&g_accesslist_mutex); | 370 | pthread_mutex_unlock(&g_accesslist_mutex); |
| 361 | } | 371 | } |
| 362 | 372 | ||
| 373 | free(line); | ||
| 363 | fclose(fifo); | 374 | fclose(fifo); |
| 364 | } | 375 | } |
| 365 | return NULL; | 376 | return NULL; |
| @@ -367,11 +378,30 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_ | |||
| 367 | 378 | ||
| 368 | static void *accesslist_adder_worker(void *args) { | 379 | static void *accesslist_adder_worker(void *args) { |
| 369 | (void)args; | 380 | (void)args; |
| 370 | return accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete); | 381 | accesslist_adddel_worker(g_accesslist_pipe_add, &g_accesslist_add, &g_accesslist_delete); |
| 382 | atomic_store(&adder_left, 1); | ||
| 383 | return NULL; | ||
| 371 | } | 384 | } |
| 372 | static void *accesslist_deleter_worker(void *args) { | 385 | static void *accesslist_deleter_worker(void *args) { |
| 373 | (void)args; | 386 | (void)args; |
| 374 | return accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add); | 387 | accesslist_adddel_worker(g_accesslist_pipe_delete, &g_accesslist_delete, &g_accesslist_add); |
| 388 | atomic_store(&deleter_left, 1); | ||
| 389 | return NULL; | ||
| 390 | } | ||
| 391 | |||
| 392 | /* These sit in a blocking open or read on a FIFO, so they are woken the way | ||
| 393 | the other workers are, and the signal is repeated because it only | ||
| 394 | interrupts a call already under way. The pipe name is what says whether | ||
| 395 | the thread was ever started. */ | ||
| 396 | static void accesslist_stop_fifo_worker(pthread_t thread, _Atomic int *left, const char *pipe_name) { | ||
| 397 | if (!pipe_name) | ||
| 398 | return; | ||
| 399 | |||
| 400 | while (!atomic_load(left)) { | ||
| 401 | pthread_kill(thread, OT_SIGNAL_WAKE); | ||
| 402 | usleep(1000); | ||
| 403 | } | ||
| 404 | pthread_join(thread, NULL); | ||
| 375 | } | 405 | } |
| 376 | #endif | 406 | #endif |
| 377 | 407 | ||
| @@ -392,6 +422,12 @@ void accesslist_deinit(void) { | |||
| 392 | pthread_kill(thread_id, SIGHUP); | 422 | pthread_kill(thread_id, SIGHUP); |
| 393 | pthread_join(thread_id, NULL); | 423 | pthread_join(thread_id, NULL); |
| 394 | 424 | ||
| 425 | #ifdef WANT_DYNAMIC_ACCESSLIST | ||
| 426 | /* Before the lists they are reading are freed below */ | ||
| 427 | accesslist_stop_fifo_worker(thread_adder_id, &adder_left, g_accesslist_pipe_add); | ||
| 428 | accesslist_stop_fifo_worker(thread_deleter_id, &deleter_left, g_accesslist_pipe_delete); | ||
| 429 | #endif | ||
| 430 | |||
| 395 | pthread_mutex_lock(&g_accesslist_mutex); | 431 | pthread_mutex_lock(&g_accesslist_mutex); |
| 396 | 432 | ||
| 397 | g_accesslist = accesslist_free(g_accesslist); | 433 | g_accesslist = accesslist_free(g_accesslist); |
