Make accesslists thread safe. Signal handler is working in its own thread now, waiting for a signal. All other threads ignore signals.

dynamic-accesslists
erdgeist 16 years ago
parent 57f85fc7cc
commit bb770a45a6

@ -65,6 +65,32 @@ static void signal_handler( int s ) {
}
}
static void defaul_signal_handlers( void ) {
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset (&signal_mask, SIGPIPE);
sigaddset (&signal_mask, SIGHUP);
sigaddset (&signal_mask, SIGINT);
sigaddset (&signal_mask, SIGALRM);
pthread_sigmask (SIG_BLOCK, &signal_mask, NULL);
}
static void install_signal_handlers( void ) {
struct sigaction sa;
sigset_t signal_mask;
sigemptyset(&signal_mask);
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if ((sigaction(SIGINT, &sa, NULL) == -1) || (sigaction(SIGALRM, &sa, NULL) == -1) )
panic( "install_signal_handlers" );
sigaddset (&signal_mask, SIGINT);
sigaddset (&signal_mask, SIGALRM);
pthread_sigmask (SIG_UNBLOCK, &signal_mask, NULL);
}
static void usage( char *name ) {
fprintf( stderr, "Usage: %s [-i ip] [-p port] [-P port] [-r redirect] [-d dir] [-A ip] [-f config] [-s livesyncport]"
#ifdef WANT_ACCESSLIST_BLACK
@ -254,12 +280,14 @@ static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
#endif
#ifdef _DEBUG
{
char *protos[] = {"TCP","UDP","UDP mcast"};
char _debug[512];
int off = snprintf( _debug, sizeof(_debug), "Binding socket type %s to address [", protos[proto] );
off += fmt_ip6c( _debug+off, ip);
snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
fputs( _debug, stderr );
}
#endif
if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 )
@ -540,10 +568,6 @@ while( scanon ) {
if( drop_privileges( g_serverdir ? g_serverdir : "." ) == -1 )
panic( "drop_privileges failed, exiting. Last error");
signal( SIGPIPE, SIG_IGN );
signal( SIGINT, signal_handler );
signal( SIGALRM, signal_handler );
g_now_seconds = time( NULL );
/* Create our self pipe which allows us to interrupt mainloops
@ -555,8 +579,10 @@ while( scanon ) {
io_setcookie( g_self_pipe[0], (void*)FLAG_SELFPIPE );
io_wantread( g_self_pipe[0] );
defaul_signal_handlers( );
/* Init all sub systems. This call may fail with an exit() */
trackerlogic_init( );
install_signal_handlers( );
/* Kick off our initial clock setting alarm */
alarm(5);

@ -4,6 +4,7 @@
$id$ */
/* System */
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -26,25 +27,18 @@
char *g_accesslist_filename;
static ot_hash *g_accesslist;
static size_t g_accesslist_size;
static pthread_mutex_t g_accesslist_mutex;
static int vector_compare_hash(const void *hash1, const void *hash2 ) {
return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
}
void accesslist_deinit( void ) {
free( g_accesslist );
g_accesslist = 0;
g_accesslist_size = 0;
}
/* Read initial access list */
static void accesslist_readfile( int sig ) {
ot_hash *info_hash, *accesslist_new = NULL, *accesslist_old;
static void accesslist_readfile( void ) {
ot_hash *info_hash, *accesslist_new = NULL;
char *map, *map_end, *read_offs;
size_t maplen;
if( sig != SIGHUP ) return;
if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) {
char *wd = getcwd( NULL, 0 );
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 ) {
while( read_offs < map_end && *(read_offs++) != '\n' );
}
#ifdef _DEBUG
fprintf( stderr, "Added %d info_hashes to accesslist\n", info_hash - accesslist_new );
fprintf( stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new) );
#endif
mmap_unmap( map, maplen);
@ -92,15 +86,20 @@ static void accesslist_readfile( int sig ) {
qsort( accesslist_new, info_hash - accesslist_new, sizeof( *info_hash ), vector_compare_hash );
/* Now exchange the accesslist vector in the least race condition prone way */
g_accesslist_size = 0;
accesslist_old = g_accesslist;
pthread_mutex_lock(&g_accesslist_mutex);
free( g_accesslist );
g_accesslist = accesslist_new;
g_accesslist_size = info_hash - accesslist_new;
free( accesslist_old );
pthread_mutex_unlock(&g_accesslist_mutex);
}
int accesslist_hashisvalid( ot_hash hash ) {
void *exactmatch = bsearch( hash, g_accesslist, g_accesslist_size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
void *exactmatch;
/* Lock should hardly ever be contended */
pthread_mutex_lock(&g_accesslist_mutex);
exactmatch = bsearch( hash, g_accesslist, g_accesslist_size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
pthread_mutex_unlock(&g_accesslist_mutex);
#ifdef WANT_ACCESSLIST_BLACK
return exactmatch == NULL;
@ -109,12 +108,38 @@ int accesslist_hashisvalid( ot_hash hash ) {
#endif
}
static void * accesslist_worker( void * args ) {
int sig;
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGHUP);
(void)args;
while( 1 ) {
/* Initial attempt to read accesslist */
accesslist_readfile( );
/* Wait for signals */
while( sigwait (&signal_mask, &sig) != 0 && sig != SIGHUP );
}
return NULL;
}
static pthread_t thread_id;
void accesslist_init( ) {
/* Passing "0" since read_blacklist_file also is SIGHUP handler */
if( g_accesslist_filename ) {
accesslist_readfile( SIGHUP );
signal( SIGHUP, accesslist_readfile );
pthread_mutex_init(&g_accesslist_mutex, NULL);
pthread_create( &thread_id, NULL, accesslist_worker, NULL );
}
void accesslist_deinit( void ) {
pthread_cancel( thread_id );
pthread_mutex_destroy(&g_accesslist_mutex);
free( g_accesslist );
g_accesslist = 0;
g_accesslist_size = 0;
}
#endif

Loading…
Cancel
Save