mirror of
https://erdgeist.org/gitweb/opentracker
synced 2024-05-10 07:54:50 +00:00
Make accesslists thread safe. Signal handler is working in its own thread now, waiting for a signal. All other threads ignore signals.
This commit is contained in:
@ -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 )
|
||||
@ -483,7 +511,7 @@ int main( int argc, char **argv ) {
|
||||
noipv6=1;
|
||||
#endif
|
||||
|
||||
while( scanon ) {
|
||||
while( scanon ) {
|
||||
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:l:v"
|
||||
#ifdef WANT_ACCESSLIST_BLACK
|
||||
"b:"
|
||||
@ -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
|
||||
}
|
||||
|
||||
void accesslist_init( ) {
|
||||
/* Passing "0" since read_blacklist_file also is SIGHUP handler */
|
||||
if( g_accesslist_filename ) {
|
||||
accesslist_readfile( SIGHUP );
|
||||
signal( SIGHUP, accesslist_readfile );
|
||||
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( ) {
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user