From: Nick Mathewson Date: Tue, 17 Nov 2015 13:49:30 +0000 (-0500) Subject: Be more conservative in scanning the list of pending streams X-Git-Tag: tor-0.2.8.1-alpha~231^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=84b3350c83a995a7668c16cb06ae069664dc0633;p=thirdparty%2Ftor.git Be more conservative in scanning the list of pending streams Now we only re-scan the list in the cases we did before: when we have a new circuit that we should try attaching to, or when we have added a new stream that we haven't tried to attach yet. This is part of 17590. --- diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 3a1d154178..5b24425877 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1475,7 +1475,7 @@ circuit_has_opened(origin_circuit_t *circ) case CIRCUIT_PURPOSE_C_ESTABLISH_REND: rend_client_rendcirc_has_opened(circ); /* Start building an intro circ if we don't have one yet. */ - connection_ap_attach_pending(); + connection_ap_attach_pending(1); /* This isn't a call to circuit_try_attaching_streams because a * circuit in _C_ESTABLISH_REND state isn't connected to its * hidden service yet, thus we can't attach streams to it yet, @@ -1537,14 +1537,14 @@ void circuit_try_attaching_streams(origin_circuit_t *circ) { /* Attach streams to this circuit if we can. */ - connection_ap_attach_pending(); + connection_ap_attach_pending(1); /* The call to circuit_try_clearing_isolation_state here will do * nothing and return 0 if we didn't attach any streams to circ * above. */ if (circuit_try_clearing_isolation_state(circ)) { /* Maybe *now* we can attach some streams to this circuit. */ - connection_ap_attach_pending(); + connection_ap_attach_pending(1); } } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index ce6bacefd3..20a27dc90c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -512,6 +512,8 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) /* XXXXX Free this list on exit. */ static smartlist_t *pending_entry_connections = NULL; +static int untried_pending_connections = 0; + /** Common code to connection_(ap|exit)_about_to_close. */ static void connection_edge_about_to_close(edge_connection_t *edge_conn) @@ -766,24 +768,31 @@ connection_ap_rescan_and_attach_pending(void) "in pending_entry_connections, but wasn't. No worries; " "adding it.", pending_entry_connections); + untried_pending_connections = 1; smartlist_add(pending_entry_connections, entry_conn); } } SMARTLIST_FOREACH_END(conn); - connection_ap_attach_pending(); + connection_ap_attach_pending(1); } /** Tell any AP streams that are listed as waiting for a new circuit to try * again, either attaching to an available circ or launching a new one. + * + * If retry is false, only check the list if it contains at least one + * streams that we have not yet tried to attach to a circuit. */ void -connection_ap_attach_pending(void) +connection_ap_attach_pending(int retry) { if (PREDICT_UNLIKELY(!pending_entry_connections)) { return; } + if (untried_pending_connections == 0 && !retry) + return; + SMARTLIST_FOREACH_BEGIN(pending_entry_connections, entry_connection_t *, entry_conn) { connection_t *conn = ENTRY_TO_CONN(entry_conn); @@ -811,6 +820,8 @@ connection_ap_attach_pending(void) } } SMARTLIST_FOREACH_END(entry_conn); + + untried_pending_connections = 0; } /** Mark entry_conn as needing to get attached to a circuit. @@ -838,6 +849,7 @@ connection_ap_mark_as_pending_circuit(entry_connection_t *entry_conn) return; } + untried_pending_connections = 1; smartlist_add(pending_entry_connections, entry_conn); } diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 203099976f..86f3fe990c 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -65,7 +65,7 @@ int connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit); void connection_ap_expire_beginning(void); void connection_ap_rescan_and_attach_pending(void); -void connection_ap_attach_pending(void); +void connection_ap_attach_pending(int retry); void connection_ap_mark_as_pending_circuit(entry_connection_t *entry_conn); void connection_ap_fail_onehop(const char *failed_digest, cpath_build_state_t *build_state); diff --git a/src/or/main.c b/src/or/main.c index bfa41b964c..0fe818d74f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2505,10 +2505,10 @@ run_main_loop_once(void) } } - /* This should be pretty fast if nothing is pending. BUT... watch out; - * we need to make sure it doesn't show up in the profiles. five times a - * second would be enough, for instance. */ - connection_ap_attach_pending(); + /* This will be pretty fast if nothing new is pending. Note that this gets + * called once per libevent loop, which will make it happen once per group + * of events that fire, or once per second. */ + connection_ap_attach_pending(0); return 1; } diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 3846ef0c32..b8a4b2ab9b 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -52,7 +52,7 @@ rend_client_introcirc_has_opened(origin_circuit_t *circ) tor_assert(circ->cpath); log_info(LD_REND,"introcirc is open"); - connection_ap_attach_pending(); + connection_ap_attach_pending(1); } /** Send the establish-rendezvous cell along a rendezvous circuit. if @@ -1107,7 +1107,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, * than trying to attach them all. See comments bug 743. */ /* If we already have the introduction circuit built, make sure we send * the INTRODUCE cell _now_ */ - connection_ap_attach_pending(); + connection_ap_attach_pending(1); return 0; }