summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2010-04-23 19:46:29 -0400
committerRoger Dingledine <arma@torproject.org>2010-04-23 19:46:29 -0400
commitb3019c6d2b0314042dfffade021497db51e4964a (patch)
tree70ea163b4f88d46029e2d3869758bfa15ec03359
parent45ab6959c9b77ffbc03ff6b7515f1c7d0af35d45 (diff)
parentb2641920835b046ae820c608136dfbef1a557fb0 (diff)
downloadtor-b3019c6d2b0314042dfffade021497db51e4964a.tar.gz
tor-b3019c6d2b0314042dfffade021497db51e4964a.zip
Merge branch 'maint-0.2.1'
-rw-r--r--changes/close_begindir_circs7
-rw-r--r--src/or/circuituse.c53
-rw-r--r--src/or/main.c4
-rw-r--r--src/or/or.h2
4 files changed, 63 insertions, 3 deletions
diff --git a/changes/close_begindir_circs b/changes/close_begindir_circs
new file mode 100644
index 0000000000..3b1ee879c5
--- /dev/null
+++ b/changes/close_begindir_circs
@@ -0,0 +1,7 @@
+ o Major bugfixes:
+ - Relays now close idle circuits early if it looks like they were
+ intended for directory fetches. Such circuits are unlikely to
+ be re-used, and tens of thousands of them were piling up at the
+ fast relays, causing the relays to run out of sockets and memory.
+ Bugfix on 0.2.0.22-rc (where clients started tunneling their
+ directory fetches over TLS).
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 9eda9e2480..7e47e60559 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -17,7 +17,7 @@ extern circuit_t *global_circuitlist; /* from circuitlist.c */
/********* END VARIABLES ************/
-static void circuit_expire_old_circuits(time_t now);
+static void circuit_expire_old_circuits_clientside(time_t now);
static void circuit_increment_failure_count(void);
long int lround(double x);
@@ -567,7 +567,7 @@ circuit_build_needed_circs(time_t now)
time_to_new_circuit = now + options->NewCircuitPeriod;
if (proxy_mode(get_options()))
addressmap_clean(now);
- circuit_expire_old_circuits(now);
+ circuit_expire_old_circuits_clientside(now);
#if 0 /* disable for now, until predict-and-launch-new can cull leftovers */
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
@@ -656,7 +656,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
* for too long and has no streams on it: mark it for close.
*/
static void
-circuit_expire_old_circuits(time_t now)
+circuit_expire_old_circuits_clientside(time_t now)
{
circuit_t *circ;
time_t cutoff;
@@ -696,6 +696,53 @@ circuit_expire_old_circuits(time_t now)
}
}
+/** How long do we wait before killing circuits with the properties
+ * described below?
+ *
+ * Probably we could choose a number here as low as 5 to 10 seconds,
+ * since these circs are used for begindir, and a) generally you either
+ * ask another begindir question right after or you don't for a long time,
+ * b) clients at least through 0.2.1.x choose from the whole set of
+ * directory mirrors at each choice, and c) re-establishing a one-hop
+ * circuit via create-fast is a light operation assuming the TLS conn is
+ * still there.
+ *
+ * I expect "b" to go away one day when we move to using directory
+ * guards, but I think "a" and "c" are good enough reasons that a low
+ * number is safe even then.
+ */
+#define IDLE_ONE_HOP_CIRC_TIMEOUT 60
+
+/** Find each non-origin circuit that has been unused for too long,
+ * has no streams on it, used a create_fast, and ends here: mark it
+ * for close.
+ */
+void
+circuit_expire_old_circuits_serverside(time_t now)
+{
+ circuit_t *circ;
+ or_circuit_t *or_circ;
+ time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT;
+
+ for (circ = global_circuitlist; circ; circ = circ->next) {
+ if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ))
+ continue;
+ or_circ = TO_OR_CIRCUIT(circ);
+ /* If the circuit has been idle for too long, and there are no streams
+ * on it, and it ends here, and it used a create_fast, mark it for close.
+ */
+ if (or_circ->is_first_hop && !circ->n_conn &&
+ !or_circ->n_streams && !or_circ->resolving_streams &&
+ or_circ->p_conn &&
+ or_circ->p_conn->timestamp_last_added_nonpadding <= cutoff) {
+ log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)",
+ or_circ->p_circ_id,
+ (int)(now - or_circ->p_conn->timestamp_last_added_nonpadding));
+ circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
+ }
+ }
+}
+
/** Number of testing circuits we want open before testing our bandwidth. */
#define NUM_PARALLEL_TESTING_CIRCS 4
diff --git a/src/or/main.c b/src/or/main.c
index ccc25c5636..017f72baca 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1134,6 +1134,10 @@ run_scheduled_events(time_t now)
if (have_dir_info && !we_are_hibernating())
circuit_build_needed_circs(now);
+ /* every 10 seconds, but not at the same second as other such events */
+ if (now % 10 == 5)
+ circuit_expire_old_circuits_serverside(now);
+
/** 5. We do housekeeping for each connection... */
connection_or_set_bad_connections();
for (i=0;i<smartlist_len(connection_array);i++) {
diff --git a/src/or/or.h b/src/or/or.h
index 46885482a8..9c613d28d1 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3230,6 +3230,8 @@ int circuit_conforms_to_options(const origin_circuit_t *circ,
void circuit_build_needed_circs(time_t now);
void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
+void circuit_expire_old_circuits_serverside(time_t now);
+
void reset_bandwidth_test(void);
int circuit_enough_testing_circs(void);