diff options
| -rw-r--r-- | src/ot_accesslist.c | 16 | ||||
| -rw-r--r-- | src/ot_accesslist.h | 5 | ||||
| -rw-r--r-- | tests/integration/test_accesslist.py | 24 |
3 files changed, 34 insertions, 11 deletions
diff --git a/src/ot_accesslist.c b/src/ot_accesslist.c index ea5bdba..0597e9a 100644 --- a/src/ot_accesslist.c +++ b/src/ot_accesslist.c | |||
| @@ -33,7 +33,7 @@ const char *g_accesslist_filename = NULL; | |||
| 33 | const char *g_accesslist_pipe_add = NULL; | 33 | const char *g_accesslist_pipe_add = NULL; |
| 34 | const char *g_accesslist_pipe_delete = NULL; | 34 | const char *g_accesslist_pipe_delete = NULL; |
| 35 | #endif | 35 | #endif |
| 36 | static pthread_mutex_t g_accesslist_mutex; | 36 | static pthread_mutex_t g_accesslist_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 37 | 37 | ||
| 38 | /* Accesslists are lock free linked lists. We can not make them locking, because every announce | 38 | /* Accesslists are lock free linked lists. We can not make them locking, because every announce |
| 39 | would try to acquire the mutex, making it the most contested mutex in the whole of opentracker, | 39 | would try to acquire the mutex, making it the most contested mutex in the whole of opentracker, |
| @@ -257,15 +257,14 @@ static void *accesslist_worker(void *args) { | |||
| 257 | (void)args; | 257 | (void)args; |
| 258 | 258 | ||
| 259 | while (1) { | 259 | while (1) { |
| 260 | /* Wait for signals */ | ||
| 261 | while (sigwait(&signal_mask, &sig) != 0) | ||
| 262 | ; | ||
| 263 | |||
| 260 | if (!g_opentracker_running) | 264 | if (!g_opentracker_running) |
| 261 | return NULL; | 265 | return NULL; |
| 262 | 266 | ||
| 263 | /* Initial attempt to read accesslist */ | ||
| 264 | accesslist_readfile(); | 267 | accesslist_readfile(); |
| 265 | |||
| 266 | /* Wait for signals */ | ||
| 267 | while (sigwait(&signal_mask, &sig) != 0 && sig != SIGHUP) | ||
| 268 | ; | ||
| 269 | } | 268 | } |
| 270 | return NULL; | 269 | return NULL; |
| 271 | } | 270 | } |
| @@ -405,7 +404,9 @@ static void accesslist_stop_fifo_worker(pthread_t thread, _Atomic int *left, con | |||
| 405 | 404 | ||
| 406 | static pthread_t thread_id; | 405 | static pthread_t thread_id; |
| 407 | void accesslist_init(void) { | 406 | void accesslist_init(void) { |
| 408 | pthread_mutex_init(&g_accesslist_mutex, NULL); | 407 | /* Everything that consults the list starts after this returns */ |
| 408 | accesslist_readfile(); | ||
| 409 | |||
| 409 | pthread_create(&thread_id, NULL, accesslist_worker, NULL); | 410 | pthread_create(&thread_id, NULL, accesslist_worker, NULL); |
| 410 | #ifdef WANT_DYNAMIC_ACCESSLIST | 411 | #ifdef WANT_DYNAMIC_ACCESSLIST |
| 411 | if (g_accesslist_pipe_add) | 412 | if (g_accesslist_pipe_add) |
| @@ -436,7 +437,6 @@ void accesslist_deinit(void) { | |||
| 436 | #endif | 437 | #endif |
| 437 | 438 | ||
| 438 | pthread_mutex_unlock(&g_accesslist_mutex); | 439 | pthread_mutex_unlock(&g_accesslist_mutex); |
| 439 | pthread_mutex_destroy(&g_accesslist_mutex); | ||
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | void accesslist_cleanup(void) { | 442 | void accesslist_cleanup(void) { |
diff --git a/src/ot_accesslist.h b/src/ot_accesslist.h index 68c88dc..c0f3fc2 100644 --- a/src/ot_accesslist.h +++ b/src/ot_accesslist.h | |||
| @@ -12,8 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | #if defined(WANT_ACCESSLIST_BLACK) || defined(WANT_ACCESSLIST_WHITE) | 13 | #if defined(WANT_ACCESSLIST_BLACK) || defined(WANT_ACCESSLIST_WHITE) |
| 14 | #define WANT_ACCESSLIST | 14 | #define WANT_ACCESSLIST |
| 15 | /* Starts a thread that rereads the list when sent SIGHUP, and is stopped by | 15 | /* Reads the list, then starts a thread that rereads it when sent SIGHUP and |
| 16 | being sent one, so the caller blocks SIGHUP process wide beforehand */ | 16 | is stopped by being sent one, so the caller blocks SIGHUP process wide |
| 17 | beforehand */ | ||
| 17 | void accesslist_init(void); | 18 | void accesslist_init(void); |
| 18 | void accesslist_deinit(void); | 19 | void accesslist_deinit(void); |
| 19 | int accesslist_hashisvalid(const ot_hash hash); | 20 | int accesslist_hashisvalid(const ot_hash hash); |
diff --git a/tests/integration/test_accesslist.py b/tests/integration/test_accesslist.py index 41ff654..1c84ccf 100644 --- a/tests/integration/test_accesslist.py +++ b/tests/integration/test_accesslist.py | |||
| @@ -5,10 +5,11 @@ entry, and the file parser has to cope with the shapes an operator actually | |||
| 5 | produces: an empty file, and a last line with no newline after it. | 5 | produces: an empty file, and a last line with no newline after it. |
| 6 | """ | 6 | """ |
| 7 | 7 | ||
| 8 | import os | ||
| 8 | import struct | 9 | import struct |
| 9 | import unittest | 10 | import unittest |
| 10 | 11 | ||
| 11 | from harness import TrackerTestCase | 12 | from harness import Tracker, TrackerTestCase |
| 12 | 13 | ||
| 13 | BLOCKED = b"\xb1" * 20 | 14 | BLOCKED = b"\xb1" * 20 |
| 14 | ALLOWED = b"\xa1" * 20 | 15 | ALLOWED = b"\xa1" * 20 |
| @@ -96,5 +97,26 @@ class MissingBlacklist(TrackerTestCase): | |||
| 96 | self.assertEqual(self.tracker.announce(BLOCKED, port=6881, left=0)[b"complete"], 1) | 97 | self.assertEqual(self.tracker.announce(BLOCKED, port=6881, left=0)[b"complete"], 1) |
| 97 | 98 | ||
| 98 | 99 | ||
| 100 | class ListIsInPlaceBeforeTheStateFile(TrackerTestCase): | ||
| 101 | """The loader used to run in a thread of its own, so a state file read at | ||
| 102 | startup was checked against a list that was still empty.""" | ||
| 103 | |||
| 104 | config = "access.blacklist {dir}/blacklist\n" | ||
| 105 | files = {"blacklist": listing(BLOCKED)} | ||
| 106 | |||
| 107 | def test_a_blacklisted_torrent_in_a_state_file_is_not_restored(self): | ||
| 108 | path = os.path.join(self.tracker.dir, "state") | ||
| 109 | with open(path, "w") as handle: | ||
| 110 | handle.write("%s:5:7\n%s:5:7\n" % (BLOCKED.hex(), ALLOWED.hex())) | ||
| 111 | |||
| 112 | restarted = Tracker(self.config, self.files, extra_args=["-l", path]) | ||
| 113 | try: | ||
| 114 | self.assertNotIn(BLOCKED, restarted.scrape(BLOCKED)[b"files"], "the blacklist was not in place when the state file was read") | ||
| 115 | self.assertIn(ALLOWED, restarted.scrape(ALLOWED)[b"files"], "the state file was not read at all") | ||
| 116 | restarted.stop() | ||
| 117 | finally: | ||
| 118 | restarted._cleanup() | ||
| 119 | |||
| 120 | |||
| 99 | if __name__ == "__main__": | 121 | if __name__ == "__main__": |
| 100 | unittest.main() | 122 | unittest.main() |
