summaryrefslogtreecommitdiff
path: root/src/or/main.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2017-10-20 10:16:00 -0400
committerNick Mathewson <nickm@torproject.org>2017-10-20 11:39:17 -0400
commitf0c3b6238168e351835fdc64b5c93b84d6528870 (patch)
tree1e6a1eacb456a8b60edda037e2e5e426ad5111b7 /src/or/main.c
parent78cbced45cd244c8aab84e6fb8087b852769f5bc (diff)
downloadtor-f0c3b6238168e351835fdc64b5c93b84d6528870.tar.gz
tor-f0c3b6238168e351835fdc64b5c93b84d6528870.zip
Expose a new function to make the event loop exit once and for all.
Instead of calling tor_cleanup(), exit(x), we can now call tor_shutdown_event_loop_and_exit.
Diffstat (limited to 'src/or/main.c')
-rw-r--r--src/or/main.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/or/main.c b/src/or/main.c
index e3a73ef03e..6af61d5132 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -192,6 +192,14 @@ static smartlist_t *active_linked_connection_lst = NULL;
* <b>loop_once</b>. If so, there's no need to trigger a loopexit in order
* to handle linked connections. */
static int called_loop_once = 0;
+/** Flag: if true, it's time to shut down, so the main loop should exit as
+ * soon as possible.
+ */
+static int main_loop_should_exit = 0;
+/** The return value that the main loop should yield when it exits, if
+ * main_loop_should_exit is true.
+ */
+static int main_loop_exit_value = 0;
/** We set this to 1 when we've opened a circuit, so we can print a log
* entry to inform the user that Tor is working. We set it to 0 when
@@ -648,6 +656,30 @@ tell_event_loop_to_run_external_code(void)
}
}
+/**
+ * After finishing the current callback (if any), shut down the main loop,
+ * clean up the process, and exit with <b>exitcode</b>.
+ */
+void
+tor_shutdown_event_loop_and_exit(int exitcode)
+{
+ if (main_loop_should_exit)
+ return; /* Ignore multiple calls to this function. */
+
+ main_loop_should_exit = 1;
+ main_loop_exit_value = exitcode;
+
+ /* Unlike loopexit, loopbreak prevents other callbacks from running. */
+ tor_event_base_loopbreak(tor_libevent_get_base());
+}
+
+/** Return true iff tor_shutdown_event_loop_and_exit() has been called. */
+int
+tor_event_loop_shutdown_is_pending(void)
+{
+ return main_loop_should_exit;
+}
+
/** Helper: Tell the main loop to begin reading bytes into <b>conn</b> from
* its linked connection, if it is not doing so already. Called by
* connection_start_reading and connection_start_writing as appropriate. */
@@ -2595,6 +2627,9 @@ do_main_loop(void)
}
#endif /* defined(HAVE_SYSTEMD) */
+ main_loop_should_exit = 0;
+ main_loop_exit_value = 0;
+
return run_main_loop_until_done();
}
@@ -2610,6 +2645,9 @@ run_main_loop_once(void)
if (nt_service_is_stopping())
return 0;
+ if (main_loop_should_exit)
+ return 0;
+
#ifndef _WIN32
/* Make it easier to tell whether libevent failure is our fault or not. */
errno = 0;
@@ -2656,6 +2694,9 @@ run_main_loop_once(void)
}
}
+ if (main_loop_should_exit)
+ return 0;
+
/* And here is where we put callbacks that happen "every time the event loop
* runs." They must be very fast, or else the whole Tor process will get
* slowed down.
@@ -2684,7 +2725,11 @@ run_main_loop_until_done(void)
do {
loop_result = run_main_loop_once();
} while (loop_result == 1);
- return loop_result;
+
+ if (main_loop_should_exit)
+ return main_loop_exit_value;
+ else
+ return loop_result;
}
/** Libevent callback: invoked when we get a signal.