aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-05-03 11:57:09 -0400
committerNick Mathewson <nickm@torproject.org>2018-05-03 11:57:09 -0400
commitbe9f0e5f20e37d2176ce0663b71b532c44c10c28 (patch)
tree28efed8b00bca7b4dd9054028b7a5bf0b7ce43dd
parent319505d38c459ad446caefec5446d717c2d9e4e6 (diff)
parent57f557747d7d357e3b7190070f648887831f10a0 (diff)
downloadtor-be9f0e5f20e37d2176ce0663b71b532c44c10c28.tar.gz
tor-be9f0e5f20e37d2176ce0663b71b532c44c10c28.zip
Merge remote-tracking branch 'github/ticket25949'
-rw-r--r--changes/ticket259499
-rw-r--r--src/or/main.c37
2 files changed, 35 insertions, 11 deletions
diff --git a/changes/ticket25949 b/changes/ticket25949
new file mode 100644
index 0000000000..fd87373418
--- /dev/null
+++ b/changes/ticket25949
@@ -0,0 +1,9 @@
+ o Minor features (mainloop):
+ - Move responsibility for
+ honoring delayed SIGNEWNYM requests
+ from a once-per-second callback to a callback that is only scheduled as
+ needed. Once enough items are removed from our once-per-second
+ callback, we can eliminate it entirely to conserve CPU when idle.
+ Closes ticket
+ 25949.
+
diff --git a/src/or/main.c b/src/or/main.c
index cf0df9ba79..b492166f87 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -188,6 +188,8 @@ static uint64_t stats_n_main_loop_idle = 0;
static time_t time_of_last_signewnym = 0;
/** Is there a signewnym request we're currently waiting to handle? */
static int signewnym_is_pending = 0;
+/** Mainloop event for the deferred signewnym call. */
+static mainloop_event_t *handle_deferred_signewnym_ev = NULL;
/** How many times have we called newnym? */
static unsigned newnym_epoch = 0;
@@ -1316,6 +1318,16 @@ signewnym_impl(time_t now)
control_event_signal(SIGNEWNYM);
}
+/** Callback: run a deferred signewnym. */
+static void
+handle_deferred_signewnym_cb(mainloop_event_t *event, void *arg)
+{
+ (void)event;
+ (void)arg;
+ log_info(LD_CONTROL, "Honoring delayed NEWNYM request");
+ signewnym_impl(time(NULL));
+}
+
/** Return the number of times that signewnym has been called. */
unsigned
get_signewnym_epoch(void)
@@ -1699,14 +1711,6 @@ run_scheduled_events(time_t now)
*/
consider_hibernation(now);
- /* 0b. If we've deferred a signewnym, make sure it gets handled
- * eventually. */
- if (signewnym_is_pending &&
- time_of_last_signewnym + MAX_SIGNEWNYM_RATE <= now) {
- log_info(LD_CONTROL, "Honoring delayed NEWNYM request");
- signewnym_impl(now);
- }
-
/* 0c. If we've deferred log messages for the controller, handle them now */
flush_pending_log_callbacks();
@@ -3075,10 +3079,20 @@ process_signal(int sig)
case SIGNEWNYM: {
time_t now = time(NULL);
if (time_of_last_signewnym + MAX_SIGNEWNYM_RATE > now) {
- signewnym_is_pending = 1;
+ const time_t delay_sec =
+ time_of_last_signewnym + MAX_SIGNEWNYM_RATE - now;
+ if (! signewnym_is_pending) {
+ signewnym_is_pending = 1;
+ if (!handle_deferred_signewnym_ev) {
+ handle_deferred_signewnym_ev =
+ mainloop_event_postloop_new(handle_deferred_signewnym_cb, NULL);
+ }
+ const struct timeval delay_tv = { delay_sec, 0 };
+ mainloop_event_schedule(handle_deferred_signewnym_ev, &delay_tv);
+ }
log_notice(LD_CONTROL,
- "Rate limiting NEWNYM request: delaying by %d second(s)",
- (int)(MAX_SIGNEWNYM_RATE+time_of_last_signewnym-now));
+ "Rate limiting NEWNYM request: delaying by %d second(s)",
+ (int)(delay_sec));
} else {
signewnym_impl(now);
}
@@ -3617,6 +3631,7 @@ tor_free_all(int postfork)
mainloop_event_free(directory_all_unreachable_cb_event);
mainloop_event_free(schedule_active_linked_connections_event);
mainloop_event_free(postloop_cleanup_ev);
+ mainloop_event_free(handle_deferred_signewnym_ev);
#ifdef HAVE_SYSTEMD_209
periodic_timer_free(systemd_watchdog_timer);