[tor-commits] [tor/master] Add a mostly disabled feature to debug restarting in-process

nickm at torproject.org nickm at torproject.org
Fri Jan 19 14:54:02 UTC 2018


commit 97d9ba2380e0c894a1b611bdb4f35d0fe98a837a
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Dec 11 10:57:00 2017 -0500

    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.
---
 changes/feature24583 |  9 +++++++++
 configure.ac         |  6 ++++++
 src/or/main.c        | 39 +++++++++++++++++++++++++++++++++++++++
 src/or/tor_main.c    | 16 +++++++++++++++-
 4 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/changes/feature24583 b/changes/feature24583
new file mode 100644
index 000000000..19feaec5b
--- /dev/null
+++ b/changes/feature24583
@@ -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.
diff --git a/configure.ac b/configure.ac
index ee75d3a29..36a27b54b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/src/or/main.c b/src/or/main.c
index aae98dd8a..dc954bc15 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -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();
 }
 
diff --git a/src/or/tor_main.c b/src/or/tor_main.c
index c203d8248..703669ac9 100644
--- a/src/or/tor_main.c
+++ b/src/or/tor_main.c
@@ -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;
 }





More information about the tor-commits mailing list