diff options
Diffstat (limited to 'src/or/main.c')
-rw-r--r-- | src/or/main.c | 107 |
1 files changed, 77 insertions, 30 deletions
diff --git a/src/or/main.c b/src/or/main.c index 026dcca01d..06fc541567 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -100,6 +100,7 @@ static int conn_close_if_marked(int i); static void connection_start_reading_from_linked_conn(connection_t *conn); static int connection_should_read_from_linked_conn(connection_t *conn); static int run_main_loop_until_done(void); +static void process_signal(int sig); /********* START VARIABLES **********/ @@ -2260,11 +2261,10 @@ run_main_loop_until_done(void) return loop_result; } -#ifndef _WIN32 /* Only called when we're willing to use signals */ /** Libevent callback: invoked when we get a signal. */ static void -signal_callback(int fd, short events, void *arg) +signal_callback(evutil_socket_t fd, short events, void *arg) { const int *sigptr = arg; const int sig = *sigptr; @@ -2273,10 +2273,9 @@ signal_callback(int fd, short events, void *arg) process_signal(sig); } -#endif /** Do the work of acting on a signal received in <b>sig</b> */ -void +static void process_signal(int sig) { switch (sig) @@ -2501,36 +2500,73 @@ exit_function(void) #endif } -/** Set up the signal handlers for either parent or child. */ +#ifdef _WIN32 +#define UNIX_ONLY 0 +#else +#define UNIX_ONLY 1 +#endif +static struct { + int signal_value; + int try_to_register; + struct event *signal_event; +} signal_handlers[] = { +#ifdef SIGINT + { SIGINT, UNIX_ONLY, NULL }, /* do a controlled slow shutdown */ +#endif +#ifdef SIGTERM + { SIGTERM, UNIX_ONLY, NULL }, /* to terminate now */ +#endif +#ifdef SIGPIPE + { SIGPIPE, UNIX_ONLY, NULL }, /* otherwise SIGPIPE kills us */ +#endif +#ifdef SIGUSR1 + { SIGUSR1, UNIX_ONLY, NULL }, /* dump stats */ +#endif +#ifdef SIGUSR2 + { SIGUSR2, UNIX_ONLY, NULL }, /* go to loglevel debug */ +#endif +#ifdef SIGHUP + { SIGHUP, UNIX_ONLY, NULL }, /* to reload config, retry conns, etc */ +#endif +#ifdef SIGXFSZ + { SIGXFSZ, UNIX_ONLY, NULL }, /* handle file-too-big resource exhaustion */ +#endif +#ifdef SIGCHLD + { SIGCHLD, UNIX_ONLY, NULL }, /* handle dns/cpu workers that exit */ +#endif + /* These are controller-only */ + { SIGNEWNYM, 0, NULL }, + { SIGCLEARDNSCACHE, 0, NULL }, + { SIGHEARTBEAT, 0, NULL }, + { -1, -1, NULL } +}; + +/** Set up the signal handlers for either parent or child process */ void handle_signals(int is_parent) { -#ifndef _WIN32 /* do signal stuff only on Unix */ int i; - static const int signals[] = { - SIGINT, /* do a controlled slow shutdown */ - SIGTERM, /* to terminate now */ - SIGPIPE, /* otherwise SIGPIPE kills us */ - SIGUSR1, /* dump stats */ - SIGUSR2, /* go to loglevel debug */ - SIGHUP, /* to reload config, retry conns, etc */ -#ifdef SIGXFSZ - SIGXFSZ, /* handle file-too-big resource exhaustion */ -#endif - SIGCHLD, /* handle dns/cpu workers that exit */ - -1 }; - static struct event *signal_events[16]; /* bigger than it has to be. */ if (is_parent) { - for (i = 0; signals[i] >= 0; ++i) { - signal_events[i] = tor_evsignal_new(tor_libevent_get_base(), signals[i], - signal_callback, - /* Cast away const */ - (int*)&signals[i]); - if (event_add(signal_events[i], NULL)) - log_warn(LD_BUG, "Error from libevent when adding event for signal %d", - signals[i]); + for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { + if (signal_handlers[i].try_to_register) { + signal_handlers[i].signal_event = + tor_evsignal_new(tor_libevent_get_base(), + signal_handlers[i].signal_value, + signal_callback, + &signal_handlers[i].signal_value); + if (event_add(signal_handlers[i].signal_event, NULL)) + log_warn(LD_BUG, "Error from libevent when adding " + "event for signal %d", + signal_handlers[i].signal_value); + } else { + signal_handlers[i].signal_event = + tor_event_new(tor_libevent_get_base(), -1, + EV_SIGNAL, signal_callback, + &signal_handlers[i].signal_value); + } } } else { +#ifndef _WIN32 struct sigaction action; action.sa_flags = 0; sigemptyset(&action.sa_mask); @@ -2544,10 +2580,21 @@ handle_signals(int is_parent) #ifdef SIGXFSZ sigaction(SIGXFSZ, &action, NULL); #endif +#endif + } +} + +/* Make sure the signal handler for signal_num will be called. */ +void +activate_signal(int signal_num) +{ + int i; + for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { + if (signal_handlers[i].signal_value == signal_num) { + event_active(signal_handlers[i].signal_event, EV_SIGNAL, 1); + return; + } } -#else /* MS windows */ - (void)is_parent; -#endif /* signal stuff */ } /** Main entry point for the Tor command-line client. |