From 322abc030e53c7e84ca9f22a47b2965f262f5ffa Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Dec 2017 11:33:54 -0500 Subject: [PATCH 1/4] On exit, free the event_base and set its pointer to NULL. When we didn't do this before, we'd have some still-reachable memory warnings, and we'd find ourselves crashing when we tried to reinitialize libevent. Part of 24581 (don't crash when restarting Tor in-process) --- src/common/compat_libevent.c | 10 ++++++++++ src/common/compat_libevent.h | 1 + src/or/main.c | 1 + 3 files changed, 12 insertions(+) diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 10489bf296..b5e9cc9332 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -237,6 +237,16 @@ tor_init_libevent_rng(void) return rv; } +/** + * Un-initialize libevent in preparation for an exit + */ +void +tor_libevent_free_all(void) +{ + event_base_free(the_event_base); + the_event_base = NULL; +} + #if defined(LIBEVENT_VERSION_NUMBER) && \ LIBEVENT_VERSION_NUMBER >= V(2,1,1) && \ !defined(TOR_UNIT_TESTS) diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 0cdb73fbb9..1853e50917 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -52,6 +52,7 @@ const char *tor_libevent_get_method(void); void tor_check_libevent_header_compatibility(void); const char *tor_libevent_get_version_str(void); const char *tor_libevent_get_header_version_str(void); +void tor_libevent_free_all(void); int tor_init_libevent_rng(void); diff --git a/src/or/main.c b/src/or/main.c index aae98dd8ab..bebe9fff44 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -3388,6 +3388,7 @@ tor_free_all(int postfork) if (!postfork) { release_lockfile(); } + tor_libevent_free_all(); /* Stuff in util.c and address.c*/ if (!postfork) { escaped(NULL); From 474ca13d6a5e8aa2cf099e92e68eb932b15b2315 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Dec 2017 11:37:20 -0500 Subject: [PATCH 2/4] Mark libevent unitialized on shutdown. This is necessary so that we will reinitialize it on startup. --- src/or/config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/or/config.c b/src/or/config.c index 23184af31e..e7d11df073 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -796,6 +796,8 @@ static smartlist_t *configured_ports = NULL; /** True iff we're currently validating options, and any calls to * get_options() are likely to be bugs. */ static int in_option_validation = 0; +/* True iff we've initialized libevent */ +static int libevent_initialized = 0; /** Return the contents of our frontpage string, or NULL if not configured. */ MOCK_IMPL(const char*, @@ -986,6 +988,7 @@ config_free_all(void) tor_free(the_tor_version); have_parsed_cmdline = 0; + libevent_initialized = 0; } /** Make address -- a piece of information related to our operation as @@ -1336,7 +1339,6 @@ options_act_reversible(const or_options_t *old_options, char **msg) { smartlist_t *new_listeners = smartlist_new(); smartlist_t *replaced_listeners = smartlist_new(); - static int libevent_initialized = 0; or_options_t *options = get_options_mutable(); int running_tor = options->command == CMD_RUN_TOR; int set_conn_limit = 0; From 06ffafcb9d4107297b6e72ee53d6e6db782cbdea Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Dec 2017 11:37:54 -0500 Subject: [PATCH 3/4] Set DH parameters to NULL on shutdown If we don't do this, we will use freed memory on restart. Part of 24581. --- src/common/crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/crypto.c b/src/common/crypto.c index 575bfd0c06..45aa3a02cb 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -3470,6 +3470,8 @@ crypto_global_cleanup(void) if (dh_param_g) BN_clear_free(dh_param_g); + dh_param_p = dh_param_p_tls = dh_param_g = NULL; + #ifndef DISABLE_ENGINES ENGINE_cleanup(); #endif From 3b465ebf2eedecfa0659f91a6ed7dc667e7acde7 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 11 Dec 2017 11:55:41 -0500 Subject: [PATCH 4/4] Changes file and tor_api.h tweaks for 24581. --- changes/bug24581 | 7 +++++++ src/or/tor_api.h | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changes/bug24581 diff --git a/changes/bug24581 b/changes/bug24581 new file mode 100644 index 0000000000..d8ddce3cc9 --- /dev/null +++ b/changes/bug24581 @@ -0,0 +1,7 @@ + o Major features (embedding): + - Tor now has support for restarting in the same process. + Controllers that run Tor using the "tor_api.h" interface can now + restart Tor after Tor has exited. This support is incomplete, however: + we have fixed the crash bugs that prevented it from working at all + before, but many bugs probably remain. Implements ticket 24581. + diff --git a/src/or/tor_api.h b/src/or/tor_api.h index b12ed718c1..e7d70c2a61 100644 --- a/src/or/tor_api.h +++ b/src/or/tor_api.h @@ -71,8 +71,9 @@ void tor_main_configuration_free(tor_main_configuration_t *cfg); * fix it. * * BUG 23847: You can only call tor_main() once in a single process; if it - * returns and you call it again, you may crash. This is not intended - * long-term behavior; we are trying to fix it. + * returns and you call it again, you may crash, or you may encounter other + * unexpected behavior. This is not intended long-term behavior; we are + * trying to fix it. * * LIMITATION: You cannot run more than one instance of Tor in the same * process at the same time. Concurrent calls will cause undefined behavior.