From b78803f9f543c83bf50d0751eb160e80ed602eae Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 14 Mar 2015 14:24:18 -0400 Subject: [PATCH 1/4] Extract main part of main loop into a separate function For 15176; Shadow would like this. Based on a patch by Rob Jansen, but revised to have a minimal-sized diff. --- changes/ticket15176 | 3 +++ src/or/main.c | 23 ++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 changes/ticket15176 diff --git a/changes/ticket15176 b/changes/ticket15176 new file mode 100644 index 000000000..6d1272372 --- /dev/null +++ b/changes/ticket15176 @@ -0,0 +1,3 @@ + o Code simplification and refactoring: + - Refactor main loop to extract the 'loop' part. This makes it easier + to run Tor under Shadow. Closes ticket 15176. diff --git a/src/or/main.c b/src/or/main.c index bc89458e8..f5bca4e51 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -97,6 +97,7 @@ static void second_elapsed_callback(periodic_timer_t *timer, void *args); 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); /********* START VARIABLES **********/ @@ -1955,7 +1956,6 @@ do_hup(void) int do_main_loop(void) { - int loop_result; time_t now; /* initialize dns resolve map, spawn workers if needed */ @@ -2084,7 +2084,14 @@ do_main_loop(void) } #endif - for (;;) { + return run_main_loop_until_done(); +} + +static int +run_main_loop_once(void) +{ + int loop_result; + if (1) { if (nt_service_is_stopping()) return 0; @@ -2125,10 +2132,20 @@ do_main_loop(void) log_debug(LD_NET,"libevent call interrupted."); /* You can't trust the results of this poll(). Go back to the * top of the big for loop. */ - continue; + return 1; } } } + return 1; +} + +static int +run_main_loop_until_done(void) +{ + int loop_result = 1; + while ((loop_result = run_main_loop_once()) == 1) + continue; + return loop_result; } #ifndef _WIN32 /* Only called when we're willing to use signals */ From 92d04721a2a614e40d6393ccc64ff2e86b71d778 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 14 Mar 2015 14:25:37 -0400 Subject: [PATCH 2/4] remove a needless "if (1)" that was there for indentation; fix indentation. --- src/or/main.c | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/or/main.c b/src/or/main.c index f5bca4e51..888dabedc 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2091,51 +2091,51 @@ static int run_main_loop_once(void) { int loop_result; - if (1) { - if (nt_service_is_stopping()) - return 0; + + if (nt_service_is_stopping()) + return 0; #ifndef _WIN32 - /* Make it easier to tell whether libevent failure is our fault or not. */ - errno = 0; + /* Make it easier to tell whether libevent failure is our fault or not. */ + errno = 0; #endif - /* All active linked conns should get their read events activated. */ - SMARTLIST_FOREACH(active_linked_connection_lst, connection_t *, conn, - event_active(conn->read_event, EV_READ, 1)); - called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0; + /* All active linked conns should get their read events activated. */ + SMARTLIST_FOREACH(active_linked_connection_lst, connection_t *, conn, + event_active(conn->read_event, EV_READ, 1)); + called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0; - update_approx_time(time(NULL)); + update_approx_time(time(NULL)); - /* poll until we have an event, or the second ends, or until we have - * some active linked connections to trigger events for. */ - loop_result = event_base_loop(tor_libevent_get_base(), - called_loop_once ? EVLOOP_ONCE : 0); + /* poll until we have an event, or the second ends, or until we have + * some active linked connections to trigger events for. */ + loop_result = event_base_loop(tor_libevent_get_base(), + called_loop_once ? EVLOOP_ONCE : 0); - /* let catch() handle things like ^c, and otherwise don't worry about it */ - if (loop_result < 0) { - int e = tor_socket_errno(-1); - /* let the program survive things like ^z */ - if (e != EINTR && !ERRNO_IS_EINPROGRESS(e)) { - log_err(LD_NET,"libevent call with %s failed: %s [%d]", - tor_libevent_get_method(), tor_socket_strerror(e), e); + /* let catch() handle things like ^c, and otherwise don't worry about it */ + if (loop_result < 0) { + int e = tor_socket_errno(-1); + /* let the program survive things like ^z */ + if (e != EINTR && !ERRNO_IS_EINPROGRESS(e)) { + log_err(LD_NET,"libevent call with %s failed: %s [%d]", + tor_libevent_get_method(), tor_socket_strerror(e), e); + return -1; +#ifndef _WIN32 + } else if (e == EINVAL) { + log_warn(LD_NET, "EINVAL from libevent: should you upgrade libevent?"); + if (got_libevent_error()) return -1; -#ifndef _WIN32 - } else if (e == EINVAL) { - log_warn(LD_NET, "EINVAL from libevent: should you upgrade libevent?"); - if (got_libevent_error()) - return -1; #endif - } else { - if (ERRNO_IS_EINPROGRESS(e)) - log_warn(LD_BUG, - "libevent call returned EINPROGRESS? Please report."); - log_debug(LD_NET,"libevent call interrupted."); - /* You can't trust the results of this poll(). Go back to the - * top of the big for loop. */ - return 1; - } + } else { + if (ERRNO_IS_EINPROGRESS(e)) + log_warn(LD_BUG, + "libevent call returned EINPROGRESS? Please report."); + log_debug(LD_NET,"libevent call interrupted."); + /* You can't trust the results of this poll(). Go back to the + * top of the big for loop. */ + return 1; } } + return 1; } From ddb1889eb8bc128ec0fca35f15b1bf90d2b629ac Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 14 Mar 2015 14:27:33 -0400 Subject: [PATCH 3/4] Add comments for new functions --- src/or/main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/or/main.c b/src/or/main.c index 888dabedc..dd21b1a8f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2087,6 +2087,10 @@ do_main_loop(void) return run_main_loop_until_done(); } +/** + * Run the main loop a single time. Return 0 for "exit"; -1 for "exit with + * error", and 1 for "run this again." + */ static int run_main_loop_once(void) { @@ -2139,6 +2143,11 @@ run_main_loop_once(void) return 1; } +/** Run the run_main_loop_once() function until it declares itself done, + * and return its final return value. + * + * Shadow won't invoke this function, so don't fill it up with things. + */ static int run_main_loop_until_done(void) { From a0f892f19094efd963564cf788be887f694be796 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 14 Mar 2015 14:30:08 -0400 Subject: [PATCH 4/4] Simplify the loop. --- src/or/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/or/main.c b/src/or/main.c index dd21b1a8f..d0fe8cbc0 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2151,10 +2151,11 @@ run_main_loop_once(void) static int run_main_loop_until_done(void) { - int loop_result = 1; - while ((loop_result = run_main_loop_once()) == 1) - continue; - return loop_result; + int loop_result = 1; + do { + loop_result = run_main_loop_once(); + } while (loop_result == 1); + return loop_result; } #ifndef _WIN32 /* Only called when we're willing to use signals */