Add a mostly disabled feature to debug restarting in-process

For 23847, we want Tor to be able to shut down and then restart in
the same process.  Here's a patch to make the Tor binary do that.
To test it, you need to build with --enable-restart-debugging, and
then you need to set the environment variable TOR_DEBUG_RESTART.
With this option, Tor will then run for 5 seconds, then restart
itself in-process without exiting.  This only happens once.

You can change the 5-second interval using
TOR_DEBUG_RESTART_AFTER_SECONDS.

Implements ticket 24583.
This commit is contained in:
Nick Mathewson 2017-12-11 10:57:00 -05:00
parent ea929e8456
commit 97d9ba2380
4 changed files with 69 additions and 1 deletions

9
changes/feature24583 Normal file
View File

@ -0,0 +1,9 @@
o Minor features (testing, debugging):
- For development purposes, Tor now has a mode in which it runs
for a few seconds, then stops, and starts again without exiting
the process. This mode is meant to help us debug various issues
with ticket 23847. To use this feature, compile with
--enable-restart-degbugging, and set the TOR_DEBUG_RESTART
environment variable. This is expected to crash a lot, and is
really meant for developers only. It will likely be removed in a future
release. Implements ticket 24583.

View File

@ -59,6 +59,8 @@ AC_ARG_ENABLE(rust,
AS_HELP_STRING(--enable-rust, [enable rust integration]))
AC_ARG_ENABLE(cargo-online-mode,
AS_HELP_STRING(--enable-cargo-online-mode, [Allow cargo to make network requests to fetch crates. For builds with rust only.]))
AC_ARG_ENABLE(restart-debugging,
AS_HELP_STRING(--enable-restart-debugging, [Build Tor with support for debugging in-process restart. Developers only.]))
if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then
AC_MSG_ERROR([Can't disable assertions outside of coverage build])
@ -107,6 +109,10 @@ AC_ARG_ENABLE(systemd,
* ) AC_MSG_ERROR(bad value for --enable-systemd) ;;
esac], [systemd=auto])
if test "$enable_restart_debugging" = "yes"; then
AC_DEFINE(ENABLE_RESTART_DEBUGGING, 1,
[Defined if we're building with support for in-process restart debugging.])
fi
# systemd support

View File

@ -682,6 +682,20 @@ shutdown_did_not_work_callback(evutil_socket_t fd, short event, void *arg)
// LCOV_EXCL_STOP
}
#ifdef ENABLE_RESTART_DEBUGGING
static struct event *tor_shutdown_event_loop_for_restart_event = NULL;
static void
tor_shutdown_event_loop_for_restart_cb(
evutil_socket_t fd, short event, void *arg)
{
(void)fd;
(void)event;
(void)arg;
tor_event_free(tor_shutdown_event_loop_for_restart_event);
tor_shutdown_event_loop_and_exit(0);
}
#endif
/**
* After finishing the current callback (if any), shut down the main loop,
* clean up the process, and exit with <b>exitcode</b>.
@ -2675,6 +2689,31 @@ do_main_loop(void)
main_loop_should_exit = 0;
main_loop_exit_value = 0;
#ifdef ENABLE_RESTART_DEBUGGING
{
static int first_time = 1;
if (first_time && getenv("TOR_DEBUG_RESTART")) {
first_time = 0;
const char *sec_str = getenv("TOR_DEBUG_RESTART_AFTER_SECONDS");
long sec;
int sec_ok=0;
if (sec_str &&
(sec = tor_parse_long(sec_str, 10, 0, INT_MAX, &sec_ok, NULL)) &&
sec_ok) {
/* Okay, we parsed the seconds. */
} else {
sec = 5;
}
struct timeval restart_after = { (time_t) sec, 0 };
tor_shutdown_event_loop_for_restart_event =
tor_evtimer_new(tor_libevent_get_base(),
tor_shutdown_event_loop_for_restart_cb, NULL);
event_add(tor_shutdown_event_loop_for_restart_event, &restart_after);
}
}
#endif
return run_main_loop_until_done();
}

View File

@ -3,6 +3,11 @@
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#include "orconfig.h"
#ifdef ENABLE_RESTART_DEBUGGING
#include <stdlib.h>
#endif
/**
* \file tor_main.c
* \brief Stub module containing a main() function.
@ -19,9 +24,18 @@ int tor_main(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
int r = tor_main(argc, argv);
int r;
#ifdef ENABLE_RESTART_DEBUGGING
int restart_count = getenv("TOR_DEBUG_RESTART") ? 1 : 0;
again:
#endif
r = tor_main(argc, argv);
if (r < 0 || r > 255)
return 1;
#ifdef ENABLE_RESTART_DEBUGGING
else if (r == 0 && restart_count--)
goto again;
#endif
else
return r;
}