summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <>2009-07-17 18:00:26 +0000
committererdgeist <>2009-07-17 18:00:26 +0000
commitbb770a45a6a6b013d52d6e0a4b27fd630e365d30 (patch)
tree074274c297fb9b28efdbeb1f101d3783165be6fb
parent57f85fc7cccab846351dc36c8c25084793b4de0a (diff)
Make accesslists thread safe. Signal handler is working in its own thread now, waiting for a signal. All other threads ignore signals.
-rw-r--r--opentracker.c36
-rw-r--r--ot_accesslist.c65
2 files changed, 76 insertions, 25 deletions
diff --git a/opentracker.c b/opentracker.c
index c36ceaa..f715424 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -65,6 +65,32 @@ static void signal_handler( int s ) {
65 } 65 }
66} 66}
67 67
68static void defaul_signal_handlers( void ) {
69 sigset_t signal_mask;
70 sigemptyset(&signal_mask);
71 sigaddset (&signal_mask, SIGPIPE);
72 sigaddset (&signal_mask, SIGHUP);
73 sigaddset (&signal_mask, SIGINT);
74 sigaddset (&signal_mask, SIGALRM);
75 pthread_sigmask (SIG_BLOCK, &signal_mask, NULL);
76}
77
78static void install_signal_handlers( void ) {
79 struct sigaction sa;
80 sigset_t signal_mask;
81 sigemptyset(&signal_mask);
82
83 sa.sa_handler = signal_handler;
84 sigemptyset(&sa.sa_mask);
85 sa.sa_flags = SA_RESTART;
86 if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1) )
87 panic( "install_signal_handlers" );
88
89 sigaddset (&signal_mask, SIGINT);
90 sigaddset (&signal_mask, SIGALRM);
91 pthread_sigmask (SIG_UNBLOCK, &signal_mask, NULL);
92}
93
68static void usage( char *name ) { 94static void usage( char *name ) {
69 fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip] [-f config] [-s livesyncport]" 95 fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip] [-f config] [-s livesyncport]"
70#ifdef WANT_ACCESSLIST_BLACK 96#ifdef WANT_ACCESSLIST_BLACK
@@ -254,12 +280,14 @@ static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
254#endif 280#endif
255 281
256#ifdef _DEBUG 282#ifdef _DEBUG
283 {
257 char *protos[] = {"TCP","UDP","UDP mcast"}; 284 char *protos[] = {"TCP","UDP","UDP mcast"};
258 char _debug[512]; 285 char _debug[512];
259 int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] ); 286 int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] );
260 off += fmt_ip6c( _debug+off, ip); 287 off += fmt_ip6c( _debug+off, ip);
261 snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port); 288 snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
262 fputs( _debug, stderr ); 289 fputs( _debug, stderr );
290 }
263#endif 291#endif
264 292
265 if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 ) 293 if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 )
@@ -483,7 +511,7 @@ int main( int argc, char **argv ) {
483 noipv6=1; 511 noipv6=1;
484#endif 512#endif
485 513
486while( scanon ) { 514 while( scanon ) {
487 switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:l:v" 515 switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:l:v"
488#ifdef WANT_ACCESSLIST_BLACK 516#ifdef WANT_ACCESSLIST_BLACK
489"b:" 517"b:"
@@ -540,10 +568,6 @@ while( scanon ) {
540 if( drop_privileges( g_serverdir ? g_serverdir : "." ) == -1 ) 568 if( drop_privileges( g_serverdir ? g_serverdir : "." ) == -1 )
541 panic( "drop_privileges failed, exiting. Last error"); 569 panic( "drop_privileges failed, exiting. Last error");
542 570
543 signal( SIGPIPE, SIG_IGN );
544 signal( SIGINT, signal_handler );
545 signal( SIGALRM, signal_handler );
546
547 g_now_seconds = time( NULL ); 571 g_now_seconds = time( NULL );
548 572
549 /* Create our self pipe which allows us to interrupt mainloops 573 /* Create our self pipe which allows us to interrupt mainloops
@@ -555,8 +579,10 @@ while( scanon ) {
555 io_setcookie( g_self_pipe[0], (void*)FLAG_SELFPIPE ); 579 io_setcookie( g_self_pipe[0], (void*)FLAG_SELFPIPE );
556 io_wantread( g_self_pipe[0] ); 580 io_wantread( g_self_pipe[0] );
557 581
582 defaul_signal_handlers( );
558 /* Init all sub systems. This call may fail with an exit() */ 583 /* Init all sub systems. This call may fail with an exit() */
559 trackerlogic_init( ); 584 trackerlogic_init( );
585 install_signal_handlers( );
560 586
561 /* Kick off our initial clock setting alarm */ 587 /* Kick off our initial clock setting alarm */
562 alarm(5); 588 alarm(5);
diff --git a/ot_accesslist.c b/ot_accesslist.c
index 65eceb7..cdf7731 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -4,6 +4,7 @@
4 $id$ */ 4 $id$ */
5 5
6/* System */ 6/* System */
7#include <pthread.h>
7#include <stdlib.h> 8#include <stdlib.h>
8#include <string.h> 9#include <string.h>
9#include <stdio.h> 10#include <stdio.h>
@@ -26,25 +27,18 @@
26 char *g_accesslist_filename; 27 char *g_accesslist_filename;
27static ot_hash *g_accesslist; 28static ot_hash *g_accesslist;
28static size_t g_accesslist_size; 29static size_t g_accesslist_size;
30static pthread_mutex_t g_accesslist_mutex;
29 31
30static int vector_compare_hash(const void *hash1, const void *hash2 ) { 32static int vector_compare_hash(const void *hash1, const void *hash2 ) {
31 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE ); 33 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
32} 34}
33 35
34void accesslist_deinit( void ) {
35 free( g_accesslist );
36 g_accesslist = 0;
37 g_accesslist_size = 0;
38}
39
40/* Read initial access list */ 36/* Read initial access list */
41static void accesslist_readfile( int sig ) { 37static void accesslist_readfile( void ) {
42 ot_hash *info_hash, *accesslist_new = NULL, *accesslist_old; 38 ot_hash *info_hash, *accesslist_new = NULL;
43 char *map, *map_end, *read_offs; 39 char *map, *map_end, *read_offs;
44 size_t maplen; 40 size_t maplen;
45 41
46 if( sig != SIGHUP ) return;
47
48 if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) { 42 if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) {
49 char *wd = getcwd( NULL, 0 ); 43 char *wd = getcwd( NULL, 0 );
50 fprintf( stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).\nPWD: %s\n", g_accesslist_filename, wd ); 44 fprintf( stderr, "Warning: Can't open accesslist file: %s (but will try to create it later, if necessary and possible).\nPWD: %s\n", g_accesslist_filename, wd );
@@ -84,7 +78,7 @@ static void accesslist_readfile( int sig ) {
84 while( read_offs < map_end && *(read_offs++) != '\n' ); 78 while( read_offs < map_end && *(read_offs++) != '\n' );
85 } 79 }
86#ifdef _DEBUG 80#ifdef _DEBUG
87 fprintf( stderr, "Added %d info_hashes to accesslist\n", info_hash - accesslist_new ); 81 fprintf( stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new) );
88#endif 82#endif
89 83
90 mmap_unmap( map, maplen); 84 mmap_unmap( map, maplen);
@@ -92,15 +86,20 @@ static void accesslist_readfile( int sig ) {
92 qsort( accesslist_new, info_hash - accesslist_new, sizeof( *info_hash ), vector_compare_hash ); 86 qsort( accesslist_new, info_hash - accesslist_new, sizeof( *info_hash ), vector_compare_hash );
93 87
94 /* Now exchange the accesslist vector in the least race condition prone way */ 88 /* Now exchange the accesslist vector in the least race condition prone way */
95 g_accesslist_size = 0; 89 pthread_mutex_lock(&g_accesslist_mutex);
96 accesslist_old = g_accesslist; 90 free( g_accesslist );
97 g_accesslist = accesslist_new; 91 g_accesslist = accesslist_new;
98 g_accesslist_size = info_hash - accesslist_new; 92 g_accesslist_size = info_hash - accesslist_new;
99 free( accesslist_old ); 93 pthread_mutex_unlock(&g_accesslist_mutex);
100} 94}
101 95
102int accesslist_hashisvalid( ot_hash hash ) { 96int accesslist_hashisvalid( ot_hash hash ) {
103 void *exactmatch = bsearch( hash, g_accesslist, g_accesslist_size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 97 void *exactmatch;
98
99 /* Lock should hardly ever be contended */
100 pthread_mutex_lock(&g_accesslist_mutex);
101 exactmatch = bsearch( hash, g_accesslist, g_accesslist_size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
102 pthread_mutex_unlock(&g_accesslist_mutex);
104 103
105#ifdef WANT_ACCESSLIST_BLACK 104#ifdef WANT_ACCESSLIST_BLACK
106 return exactmatch == NULL; 105 return exactmatch == NULL;
@@ -109,12 +108,38 @@ int accesslist_hashisvalid( ot_hash hash ) {
109#endif 108#endif
110} 109}
111 110
112void accesslist_init( ) { 111static void * accesslist_worker( void * args ) {
113 /* Passing "0" since read_blacklist_file also is SIGHUP handler */ 112 int sig;
114 if( g_accesslist_filename ) { 113 sigset_t signal_mask;
115 accesslist_readfile( SIGHUP ); 114
116 signal( SIGHUP, accesslist_readfile ); 115 sigemptyset(&signal_mask);
116 sigaddset(&signal_mask, SIGHUP);
117
118 (void)args;
119
120 while( 1 ) {
121
122 /* Initial attempt to read accesslist */
123 accesslist_readfile( );
124
125 /* Wait for signals */
126 while( sigwait (&signal_mask, &sig) != 0 && sig != SIGHUP );
117 } 127 }
128 return NULL;
129}
130
131static pthread_t thread_id;
132void accesslist_init( ) {
133 pthread_mutex_init(&g_accesslist_mutex, NULL);
134 pthread_create( &thread_id, NULL, accesslist_worker, NULL );
135}
136
137void accesslist_deinit( void ) {
138 pthread_cancel( thread_id );
139 pthread_mutex_destroy(&g_accesslist_mutex);
140 free( g_accesslist );
141 g_accesslist = 0;
142 g_accesslist_size = 0;
118} 143}
119#endif 144#endif
120 145