summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ot_accesslist.c16
-rw-r--r--src/ot_accesslist.h5
-rw-r--r--tests/integration/test_accesslist.py24
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;
33const char *g_accesslist_pipe_add = NULL; 33const char *g_accesslist_pipe_add = NULL;
34const char *g_accesslist_pipe_delete = NULL; 34const char *g_accesslist_pipe_delete = NULL;
35#endif 35#endif
36static pthread_mutex_t g_accesslist_mutex; 36static 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
406static pthread_t thread_id; 405static pthread_t thread_id;
407void accesslist_init(void) { 406void 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
442void accesslist_cleanup(void) { 442void 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 */
17void accesslist_init(void); 18void accesslist_init(void);
18void accesslist_deinit(void); 19void accesslist_deinit(void);
19int accesslist_hashisvalid(const ot_hash hash); 20int 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
5produces: an empty file, and a last line with no newline after it. 5produces: an empty file, and a last line with no newline after it.
6""" 6"""
7 7
8import os
8import struct 9import struct
9import unittest 10import unittest
10 11
11from harness import TrackerTestCase 12from harness import Tracker, TrackerTestCase
12 13
13BLOCKED = b"\xb1" * 20 14BLOCKED = b"\xb1" * 20
14ALLOWED = b"\xa1" * 20 15ALLOWED = 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
100class 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
99if __name__ == "__main__": 121if __name__ == "__main__":
100 unittest.main() 122 unittest.main()