Merge branch 'bug10116_squashed'

This commit is contained in:
Nick Mathewson 2014-08-20 14:52:24 -04:00
commit 01a0ab02a3
13 changed files with 125 additions and 112 deletions

3
changes/bug10116 Normal file
View File

@ -0,0 +1,3 @@
o Minor features:
- When handling a low-memory situation, allocate less memory
for teporary data structures. Fixes issue 10115.

View File

@ -1140,11 +1140,10 @@ pathbias_count_circs_in_states(entry_guard_t *guard,
path_state_t from, path_state_t from,
path_state_t to) path_state_t to)
{ {
circuit_t *circ;
int open_circuits = 0; int open_circuits = 0;
/* Count currently open circuits. Give them the benefit of the doubt. */ /* Count currently open circuits. Give them the benefit of the doubt. */
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
origin_circuit_t *ocirc = NULL; origin_circuit_t *ocirc = NULL;
if (!CIRCUIT_IS_ORIGIN(circ) || /* didn't originate here */ if (!CIRCUIT_IS_ORIGIN(circ) || /* didn't originate here */
circ->marked_for_close) /* already counted */ circ->marked_for_close) /* already counted */
@ -1167,6 +1166,7 @@ pathbias_count_circs_in_states(entry_guard_t *guard,
open_circuits++; open_circuits++;
} }
} }
SMARTLIST_FOREACH_END(circ);
return open_circuits; return open_circuits;
} }

View File

@ -38,8 +38,7 @@
/********* START VARIABLES **********/ /********* START VARIABLES **********/
/** A global list of all circuits at this hop. */ /** A global list of all circuits at this hop. */
struct global_circuitlist_s global_circuitlist = static smartlist_t *global_circuitlist = NULL;
TOR_LIST_HEAD_INITIALIZER(global_circuitlist);
/** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */ /** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */
static smartlist_t *circuits_pending_chans = NULL; static smartlist_t *circuits_pending_chans = NULL;
@ -451,17 +450,25 @@ circuit_count_pending_on_channel(channel_t *chan)
void void
circuit_close_all_marked(void) circuit_close_all_marked(void)
{ {
circuit_t *circ, *tmp; smartlist_t *lst = circuit_get_global_list();
TOR_LIST_FOREACH_SAFE(circ, &global_circuitlist, head, tmp) SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, circ) {
if (circ->marked_for_close) /* Fix up index if SMARTLIST_DEL_CURRENT just moved this one. */
circ->global_circuitlist_idx = circ_sl_idx;
if (circ->marked_for_close) {
circ->global_circuitlist_idx = -1;
circuit_free(circ); circuit_free(circ);
SMARTLIST_DEL_CURRENT(lst, circ);
}
} SMARTLIST_FOREACH_END(circ);
} }
/** Return the head of the global linked list of circuits. */ /** Return the head of the global linked list of circuits. */
MOCK_IMPL(struct global_circuitlist_s *, MOCK_IMPL(smartlist_t *,
circuit_get_global_list,(void)) circuit_get_global_list,(void))
{ {
return &global_circuitlist; if (NULL == global_circuitlist)
global_circuitlist = smartlist_new();
return global_circuitlist;
} }
/** Function to make circ-\>state human-readable */ /** Function to make circ-\>state human-readable */
@ -678,7 +685,8 @@ init_circuit_base(circuit_t *circ)
circ->deliver_window = CIRCWINDOW_START; circ->deliver_window = CIRCWINDOW_START;
cell_queue_init(&circ->n_chan_cells); cell_queue_init(&circ->n_chan_cells);
TOR_LIST_INSERT_HEAD(&global_circuitlist, circ, head); smartlist_add(circuit_get_global_list(), circ);
circ->global_circuitlist_idx = smartlist_len(circuit_get_global_list()) - 1;
} }
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b> /** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
@ -799,7 +807,16 @@ circuit_free(circuit_t *circ)
extend_info_free(circ->n_hop); extend_info_free(circ->n_hop);
tor_free(circ->n_chan_create_cell); tor_free(circ->n_chan_create_cell);
TOR_LIST_REMOVE(circ, head); if (circ->global_circuitlist_idx != -1) {
int idx = circ->global_circuitlist_idx;
circuit_t *c2 = smartlist_get(global_circuitlist, idx);
tor_assert(c2 == circ);
smartlist_del(global_circuitlist, idx);
if (idx < smartlist_len(global_circuitlist)) {
c2 = smartlist_get(global_circuitlist, idx);
c2->global_circuitlist_idx = idx;
}
}
/* Remove from map. */ /* Remove from map. */
circuit_set_n_circid_chan(circ, 0, NULL); circuit_set_n_circid_chan(circ, 0, NULL);
@ -841,9 +858,9 @@ circuit_clear_cpath(origin_circuit_t *circ)
void void
circuit_free_all(void) circuit_free_all(void)
{ {
circuit_t *tmp, *tmp2; smartlist_t *lst = circuit_get_global_list();
TOR_LIST_FOREACH_SAFE(tmp, &global_circuitlist, head, tmp2) { SMARTLIST_FOREACH_BEGIN(lst, circuit_t *, tmp) {
if (! CIRCUIT_IS_ORIGIN(tmp)) { if (! CIRCUIT_IS_ORIGIN(tmp)) {
or_circuit_t *or_circ = TO_OR_CIRCUIT(tmp); or_circuit_t *or_circ = TO_OR_CIRCUIT(tmp);
while (or_circ->resolving_streams) { while (or_circ->resolving_streams) {
@ -853,8 +870,13 @@ circuit_free_all(void)
or_circ->resolving_streams = next_conn; or_circ->resolving_streams = next_conn;
} }
} }
tmp->global_circuitlist_idx = -1;
circuit_free(tmp); circuit_free(tmp);
} SMARTLIST_DEL_CURRENT(lst, tmp);
} SMARTLIST_FOREACH_END(tmp);
smartlist_free(lst);
global_circuitlist = NULL;
smartlist_free(circuits_pending_chans); smartlist_free(circuits_pending_chans);
circuits_pending_chans = NULL; circuits_pending_chans = NULL;
@ -932,10 +954,9 @@ circuit_dump_conn_details(int severity,
void void
circuit_dump_by_conn(connection_t *conn, int severity) circuit_dump_by_conn(connection_t *conn, int severity)
{ {
circuit_t *circ;
edge_connection_t *tmpconn; edge_connection_t *tmpconn;
TOR_LIST_FOREACH(circ, &global_circuitlist, head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
if (circ->marked_for_close) { if (circ->marked_for_close) {
@ -966,6 +987,7 @@ circuit_dump_by_conn(connection_t *conn, int severity)
} }
} }
} }
SMARTLIST_FOREACH_END(circ);
} }
/** Return the circuit whose global ID is <b>id</b>, or NULL if no /** Return the circuit whose global ID is <b>id</b>, or NULL if no
@ -973,8 +995,7 @@ circuit_dump_by_conn(connection_t *conn, int severity)
origin_circuit_t * origin_circuit_t *
circuit_get_by_global_id(uint32_t id) circuit_get_by_global_id(uint32_t id)
{ {
circuit_t *circ; SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
if (CIRCUIT_IS_ORIGIN(circ) && if (CIRCUIT_IS_ORIGIN(circ) &&
TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) { TO_ORIGIN_CIRCUIT(circ)->global_identifier == id) {
if (circ->marked_for_close) if (circ->marked_for_close)
@ -983,6 +1004,7 @@ circuit_get_by_global_id(uint32_t id)
return TO_ORIGIN_CIRCUIT(circ); return TO_ORIGIN_CIRCUIT(circ);
} }
} }
SMARTLIST_FOREACH_END(circ);
return NULL; return NULL;
} }
@ -1151,17 +1173,17 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason)
#ifdef DEBUG_CIRCUIT_UNLINK_ALL #ifdef DEBUG_CIRCUIT_UNLINK_ALL
{ {
circuit_t *circ;
smartlist_t *detached_2 = smartlist_new(); smartlist_t *detached_2 = smartlist_new();
int mismatch = 0, badlen = 0; int mismatch = 0, badlen = 0;
TOR_LIST_FOREACH(circ, &global_circuitlist, head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (circ->n_chan == chan || if (circ->n_chan == chan ||
(!CIRCUIT_IS_ORIGIN(circ) && (!CIRCUIT_IS_ORIGIN(circ) &&
TO_OR_CIRCUIT(circ)->p_chan == chan)) { TO_OR_CIRCUIT(circ)->p_chan == chan)) {
smartlist_add(detached_2, circ); smartlist_add(detached_2, circ);
} }
} }
SMARTLIST_FOREACH_END(circ);
if (smartlist_len(detached) != smartlist_len(detached_2)) { if (smartlist_len(detached) != smartlist_len(detached_2)) {
log_warn(LD_BUG, "List of detached circuits had the wrong length! " log_warn(LD_BUG, "List of detached circuits had the wrong length! "
@ -1235,8 +1257,7 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason)
origin_circuit_t * origin_circuit_t *
circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data) circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
{ {
circuit_t *circ; SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
if (!circ->marked_for_close && if (!circ->marked_for_close &&
circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) { circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
@ -1249,6 +1270,7 @@ circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
return ocirc; return ocirc;
} }
} }
SMARTLIST_FOREACH_END(circ);
return NULL; return NULL;
} }
@ -1261,14 +1283,17 @@ origin_circuit_t *
circuit_get_next_by_pk_and_purpose(origin_circuit_t *start, circuit_get_next_by_pk_and_purpose(origin_circuit_t *start,
const char *digest, uint8_t purpose) const char *digest, uint8_t purpose)
{ {
circuit_t *circ; int idx;
smartlist_t *lst = circuit_get_global_list();
tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose)); tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));
if (start == NULL) if (start == NULL)
circ = TOR_LIST_FIRST(&global_circuitlist); idx = 0;
else else
circ = TOR_LIST_NEXT(TO_CIRCUIT(start), head); idx = TO_CIRCUIT(start)->global_circuitlist_idx + 1;
for ( ; idx < smartlist_len(lst); ++idx) {
circuit_t *circ = smartlist_get(lst, idx);
for ( ; circ; circ = TOR_LIST_NEXT(circ, head)) {
if (circ->marked_for_close) if (circ->marked_for_close)
continue; continue;
if (circ->purpose != purpose) if (circ->purpose != purpose)
@ -1469,7 +1494,6 @@ origin_circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int flags) int flags)
{ {
circuit_t *circ_;
origin_circuit_t *best=NULL; origin_circuit_t *best=NULL;
int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
@ -1485,7 +1509,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
"capacity %d, internal %d", "capacity %d, internal %d",
purpose, need_uptime, need_capacity, internal); purpose, need_uptime, need_capacity, internal);
TOR_LIST_FOREACH(circ_, &global_circuitlist, head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) {
if (CIRCUIT_IS_ORIGIN(circ_) && if (CIRCUIT_IS_ORIGIN(circ_) &&
circ_->state == CIRCUIT_STATE_OPEN && circ_->state == CIRCUIT_STATE_OPEN &&
!circ_->marked_for_close && !circ_->marked_for_close &&
@ -1535,6 +1559,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
} }
} }
} }
SMARTLIST_FOREACH_END(circ_);
return best; return best;
} }
@ -1574,13 +1599,13 @@ circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum)
void void
circuit_mark_all_unused_circs(void) circuit_mark_all_unused_circs(void)
{ {
circuit_t *circ; SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
if (CIRCUIT_IS_ORIGIN(circ) && if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close && !circ->marked_for_close &&
!circ->timestamp_dirty) !circ->timestamp_dirty)
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
} }
SMARTLIST_FOREACH_END(circ);
} }
/** Go through the circuitlist; for each circuit that starts at us /** Go through the circuitlist; for each circuit that starts at us
@ -1593,14 +1618,14 @@ circuit_mark_all_unused_circs(void)
void void
circuit_mark_all_dirty_circs_as_unusable(void) circuit_mark_all_dirty_circs_as_unusable(void)
{ {
circuit_t *circ; SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
if (CIRCUIT_IS_ORIGIN(circ) && if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close && !circ->marked_for_close &&
circ->timestamp_dirty) { circ->timestamp_dirty) {
mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ)); mark_circuit_unusable_for_new_conns(TO_ORIGIN_CIRCUIT(circ));
} }
} }
SMARTLIST_FOREACH_END(circ);
} }
/** Mark <b>circ</b> to be closed next time we call /** Mark <b>circ</b> to be closed next time we call
@ -1950,9 +1975,7 @@ circuits_compare_by_oldest_queued_item_(const void **a_, const void **b_)
void void
circuits_handle_oom(size_t current_allocation) circuits_handle_oom(size_t current_allocation)
{ {
/* Let's hope there's enough slack space for this allocation here... */ smartlist_t *circlist;
smartlist_t *circlist = smartlist_new();
circuit_t *circ;
size_t mem_to_recover; size_t mem_to_recover;
size_t mem_recovered=0; size_t mem_recovered=0;
int n_circuits_killed=0; int n_circuits_killed=0;
@ -1984,17 +2007,20 @@ circuits_handle_oom(size_t current_allocation)
tor_gettimeofday_cached_monotonic(&now); tor_gettimeofday_cached_monotonic(&now);
now_ms = (uint32_t)tv_to_msec(&now); now_ms = (uint32_t)tv_to_msec(&now);
/* This algorithm itself assumes that you've got enough memory slack circlist = circuit_get_global_list();
* to actually run it. */ SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
TOR_LIST_FOREACH(circ, &global_circuitlist, head) {
circ->age_tmp = circuit_max_queued_item_age(circ, now_ms); circ->age_tmp = circuit_max_queued_item_age(circ, now_ms);
smartlist_add(circlist, circ); } SMARTLIST_FOREACH_END(circ);
}
/* This is O(n log n); there are faster algorithms we could use instead. /* This is O(n log n); there are faster algorithms we could use instead.
* Let's hope this doesn't happen enough to be in the critical path. */ * Let's hope this doesn't happen enough to be in the critical path. */
smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_); smartlist_sort(circlist, circuits_compare_by_oldest_queued_item_);
/* Fix up the indices before we run into trouble */
SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
circ->global_circuitlist_idx = circ_sl_idx;
} SMARTLIST_FOREACH_END(circ);
/* Okay, now the worst circuits are at the front of the list. Let's mark /* Okay, now the worst circuits are at the front of the list. Let's mark
* them, and reclaim their storage aggressively. */ * them, and reclaim their storage aggressively. */
SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) { SMARTLIST_FOREACH_BEGIN(circlist, circuit_t *, circ) {
@ -2026,8 +2052,6 @@ circuits_handle_oom(size_t current_allocation)
U64_PRINTF_ARG(mem_recovered), U64_PRINTF_ARG(mem_recovered),
n_circuits_killed, n_circuits_killed,
smartlist_len(circlist) - n_circuits_killed); smartlist_len(circlist) - n_circuits_killed);
smartlist_free(circlist);
} }
/** Verify that cpath layer <b>cp</b> has all of its invariants /** Verify that cpath layer <b>cp</b> has all of its invariants

View File

@ -14,9 +14,7 @@
#include "testsupport.h" #include "testsupport.h"
TOR_LIST_HEAD(global_circuitlist_s, circuit_t); MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
MOCK_DECL(struct global_circuitlist_s*, circuit_get_global_list, (void));
const char *circuit_state_to_string(int state); const char *circuit_state_to_string(int state);
const char *circuit_purpose_to_controller_string(uint8_t purpose); const char *circuit_purpose_to_controller_string(uint8_t purpose);
const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose); const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);

View File

@ -268,7 +268,6 @@ circuit_get_best(const entry_connection_t *conn,
int must_be_open, uint8_t purpose, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal) int need_uptime, int need_internal)
{ {
circuit_t *circ;
origin_circuit_t *best=NULL; origin_circuit_t *best=NULL;
struct timeval now; struct timeval now;
int intro_going_on_but_too_old = 0; int intro_going_on_but_too_old = 0;
@ -281,7 +280,7 @@ circuit_get_best(const entry_connection_t *conn,
tor_gettimeofday(&now); tor_gettimeofday(&now);
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
origin_circuit_t *origin_circ; origin_circuit_t *origin_circ;
if (!CIRCUIT_IS_ORIGIN(circ)) if (!CIRCUIT_IS_ORIGIN(circ))
continue; continue;
@ -305,6 +304,7 @@ circuit_get_best(const entry_connection_t *conn,
if (!best || circuit_is_better(origin_circ,best,conn)) if (!best || circuit_is_better(origin_circ,best,conn))
best = origin_circ; best = origin_circ;
} }
SMARTLIST_FOREACH_END(circ);
if (!best && intro_going_on_but_too_old) if (!best && intro_going_on_but_too_old)
log_info(LD_REND|LD_CIRC, "There is an intro circuit being created " log_info(LD_REND|LD_CIRC, "There is an intro circuit being created "
@ -318,11 +318,9 @@ circuit_get_best(const entry_connection_t *conn,
static int static int
count_pending_general_client_circuits(void) count_pending_general_client_circuits(void)
{ {
const circuit_t *circ;
int count = 0; int count = 0;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (circ->marked_for_close || if (circ->marked_for_close ||
circ->state == CIRCUIT_STATE_OPEN || circ->state == CIRCUIT_STATE_OPEN ||
circ->purpose != CIRCUIT_PURPOSE_C_GENERAL || circ->purpose != CIRCUIT_PURPOSE_C_GENERAL ||
@ -331,6 +329,7 @@ count_pending_general_client_circuits(void)
++count; ++count;
} }
SMARTLIST_FOREACH_END(circ);
return count; return count;
} }
@ -370,7 +369,6 @@ circuit_conforms_to_options(const origin_circuit_t *circ,
void void
circuit_expire_building(void) circuit_expire_building(void)
{ {
circuit_t *victim, *next_circ;
/* circ_times.timeout_ms and circ_times.close_ms are from /* circ_times.timeout_ms and circ_times.close_ms are from
* circuit_build_times_get_initial_timeout() if we haven't computed * circuit_build_times_get_initial_timeout() if we haven't computed
* custom timeouts yet */ * custom timeouts yet */
@ -388,7 +386,7 @@ circuit_expire_building(void)
* we want to be more lenient with timeouts, in case the * we want to be more lenient with timeouts, in case the
* user has relocated and/or changed network connections. * user has relocated and/or changed network connections.
* See bug #3443. */ * See bug #3443. */
TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, next_circ) {
if (!CIRCUIT_IS_ORIGIN(next_circ) || /* didn't originate here */ if (!CIRCUIT_IS_ORIGIN(next_circ) || /* didn't originate here */
next_circ->marked_for_close) { /* don't mess with marked circs */ next_circ->marked_for_close) { /* don't mess with marked circs */
continue; continue;
@ -402,7 +400,7 @@ circuit_expire_building(void)
any_opened_circs = 1; any_opened_circs = 1;
break; break;
} }
} } SMARTLIST_FOREACH_END(next_circ);
#define SET_CUTOFF(target, msec) do { \ #define SET_CUTOFF(target, msec) do { \
long ms = tor_lround(msec); \ long ms = tor_lround(msec); \
@ -473,9 +471,8 @@ circuit_expire_building(void)
MAX(get_circuit_build_close_time_ms()*2 + 1000, MAX(get_circuit_build_close_time_ms()*2 + 1000,
options->SocksTimeout * 1000)); options->SocksTimeout * 1000));
TOR_LIST_FOREACH(next_circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *,victim) {
struct timeval cutoff; struct timeval cutoff;
victim = next_circ;
if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */ if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */
victim->marked_for_close) /* don't mess with marked circs */ victim->marked_for_close) /* don't mess with marked circs */
continue; continue;
@ -780,7 +777,7 @@ circuit_expire_building(void)
circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT); circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT);
pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim)); pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim));
} } SMARTLIST_FOREACH_END(victim);
} }
/** For debugging #8387: track when we last called /** For debugging #8387: track when we last called
@ -800,9 +797,8 @@ circuit_log_ancient_one_hop_circuits(int age)
time_t cutoff = now - age; time_t cutoff = now - age;
int n_found = 0; int n_found = 0;
smartlist_t *log_these = smartlist_new(); smartlist_t *log_these = smartlist_new();
const circuit_t *circ;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
const origin_circuit_t *ocirc; const origin_circuit_t *ocirc;
if (! CIRCUIT_IS_ORIGIN(circ)) if (! CIRCUIT_IS_ORIGIN(circ))
continue; continue;
@ -817,6 +813,7 @@ circuit_log_ancient_one_hop_circuits(int age)
smartlist_add(log_these, (origin_circuit_t*) ocirc); smartlist_add(log_these, (origin_circuit_t*) ocirc);
} }
} }
SMARTLIST_FOREACH_END(circ);
if (n_found == 0) if (n_found == 0)
goto done; goto done;
@ -831,7 +828,7 @@ circuit_log_ancient_one_hop_circuits(int age)
int stream_num; int stream_num;
const edge_connection_t *conn; const edge_connection_t *conn;
char *dirty = NULL; char *dirty = NULL;
circ = TO_CIRCUIT(ocirc); const circuit_t *circ = TO_CIRCUIT(ocirc);
format_local_iso_time(created, format_local_iso_time(created,
(time_t)circ->timestamp_created.tv_sec); (time_t)circ->timestamp_created.tv_sec);
@ -938,7 +935,6 @@ int
circuit_stream_is_being_handled(entry_connection_t *conn, circuit_stream_is_being_handled(entry_connection_t *conn,
uint16_t port, int min) uint16_t port, int min)
{ {
circuit_t *circ;
const node_t *exitnode; const node_t *exitnode;
int num=0; int num=0;
time_t now = time(NULL); time_t now = time(NULL);
@ -946,7 +942,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
get_options()->LongLivedPorts, get_options()->LongLivedPorts,
conn ? conn->socks_request->port : port); conn ? conn->socks_request->port : port);
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (CIRCUIT_IS_ORIGIN(circ) && if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close && !circ->marked_for_close &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
@ -976,6 +972,7 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
} }
} }
} }
SMARTLIST_FOREACH_END(circ);
return 0; return 0;
} }
@ -989,7 +986,6 @@ circuit_stream_is_being_handled(entry_connection_t *conn,
static void static void
circuit_predict_and_launch_new(void) circuit_predict_and_launch_new(void)
{ {
circuit_t *circ;
int num=0, num_internal=0, num_uptime_internal=0; int num=0, num_internal=0, num_uptime_internal=0;
int hidserv_needs_uptime=0, hidserv_needs_capacity=1; int hidserv_needs_uptime=0, hidserv_needs_capacity=1;
int port_needs_uptime=0, port_needs_capacity=1; int port_needs_uptime=0, port_needs_capacity=1;
@ -997,7 +993,7 @@ circuit_predict_and_launch_new(void)
int flags = 0; int flags = 0;
/* First, count how many of each type of circuit we have already. */ /* First, count how many of each type of circuit we have already. */
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
cpath_build_state_t *build_state; cpath_build_state_t *build_state;
origin_circuit_t *origin_circ; origin_circuit_t *origin_circ;
if (!CIRCUIT_IS_ORIGIN(circ)) if (!CIRCUIT_IS_ORIGIN(circ))
@ -1020,6 +1016,7 @@ circuit_predict_and_launch_new(void)
if (build_state->need_uptime && build_state->is_internal) if (build_state->need_uptime && build_state->is_internal)
num_uptime_internal++; num_uptime_internal++;
} }
SMARTLIST_FOREACH_END(circ);
/* If that's enough, then stop now. */ /* If that's enough, then stop now. */
if (num >= MAX_UNUSED_OPEN_CIRCUITS) if (num >= MAX_UNUSED_OPEN_CIRCUITS)
@ -1223,7 +1220,6 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
static void static void
circuit_expire_old_circuits_clientside(void) circuit_expire_old_circuits_clientside(void)
{ {
circuit_t *circ;
struct timeval cutoff, now; struct timeval cutoff, now;
tor_gettimeofday(&now); tor_gettimeofday(&now);
@ -1239,7 +1235,7 @@ circuit_expire_old_circuits_clientside(void)
cutoff.tv_sec -= get_options()->CircuitIdleTimeout; cutoff.tv_sec -= get_options()->CircuitIdleTimeout;
} }
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ)) if (circ->marked_for_close || !CIRCUIT_IS_ORIGIN(circ))
continue; continue;
/* If the circuit has been dirty for too long, and there are no streams /* If the circuit has been dirty for too long, and there are no streams
@ -1291,7 +1287,7 @@ circuit_expire_old_circuits_clientside(void)
} }
} }
} }
} } SMARTLIST_FOREACH_END(circ);
} }
/** How long do we wait before killing circuits with the properties /** How long do we wait before killing circuits with the properties
@ -1318,11 +1314,10 @@ circuit_expire_old_circuits_clientside(void)
void void
circuit_expire_old_circuits_serverside(time_t now) circuit_expire_old_circuits_serverside(time_t now)
{ {
circuit_t *circ;
or_circuit_t *or_circ; or_circuit_t *or_circ;
time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT; time_t cutoff = now - IDLE_ONE_HOP_CIRC_TIMEOUT;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ)) if (circ->marked_for_close || CIRCUIT_IS_ORIGIN(circ))
continue; continue;
or_circ = TO_OR_CIRCUIT(circ); or_circ = TO_OR_CIRCUIT(circ);
@ -1339,6 +1334,7 @@ circuit_expire_old_circuits_serverside(time_t now)
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
} }
} }
SMARTLIST_FOREACH_END(circ);
} }
/** Number of testing circuits we want open before testing our bandwidth. */ /** Number of testing circuits we want open before testing our bandwidth. */
@ -1363,18 +1359,18 @@ reset_bandwidth_test(void)
int int
circuit_enough_testing_circs(void) circuit_enough_testing_circs(void)
{ {
circuit_t *circ;
int num = 0; int num = 0;
if (have_performed_bandwidth_test) if (have_performed_bandwidth_test)
return 1; return 1;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) && if (!circ->marked_for_close && CIRCUIT_IS_ORIGIN(circ) &&
circ->purpose == CIRCUIT_PURPOSE_TESTING && circ->purpose == CIRCUIT_PURPOSE_TESTING &&
circ->state == CIRCUIT_STATE_OPEN) circ->state == CIRCUIT_STATE_OPEN)
num++; num++;
} }
SMARTLIST_FOREACH_END(circ);
return num >= NUM_PARALLEL_TESTING_CIRCS; return num >= NUM_PARALLEL_TESTING_CIRCS;
} }

View File

@ -194,14 +194,14 @@ log_severity_to_event(int severity)
static void static void
clear_circ_bw_fields(void) clear_circ_bw_fields(void)
{ {
circuit_t *circ;
origin_circuit_t *ocirc; origin_circuit_t *ocirc;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!CIRCUIT_IS_ORIGIN(circ)) if (!CIRCUIT_IS_ORIGIN(circ))
continue; continue;
ocirc = TO_ORIGIN_CIRCUIT(circ); ocirc = TO_ORIGIN_CIRCUIT(circ);
ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0;
} }
SMARTLIST_FOREACH_END(circ);
} }
/** Set <b>global_event_mask*</b> to the bitwise OR of each live control /** Set <b>global_event_mask*</b> to the bitwise OR of each live control
@ -1879,9 +1879,8 @@ getinfo_helper_events(control_connection_t *control_conn,
{ {
(void) control_conn; (void) control_conn;
if (!strcmp(question, "circuit-status")) { if (!strcmp(question, "circuit-status")) {
circuit_t *circ_;
smartlist_t *status = smartlist_new(); smartlist_t *status = smartlist_new();
TOR_LIST_FOREACH(circ_, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) {
origin_circuit_t *circ; origin_circuit_t *circ;
char *circdesc; char *circdesc;
const char *state; const char *state;
@ -1903,6 +1902,7 @@ getinfo_helper_events(control_connection_t *control_conn,
state, *circdesc ? " " : "", circdesc); state, *circdesc ? " " : "", circdesc);
tor_free(circdesc); tor_free(circdesc);
} }
SMARTLIST_FOREACH_END(circ_);
*answer = smartlist_join_strings(status, "\r\n", 0, NULL); *answer = smartlist_join_strings(status, "\r\n", 0, NULL);
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
smartlist_free(status); smartlist_free(status);
@ -3908,12 +3908,11 @@ control_event_stream_bandwidth_used(void)
int int
control_event_circ_bandwidth_used(void) control_event_circ_bandwidth_used(void)
{ {
circuit_t *circ;
origin_circuit_t *ocirc; origin_circuit_t *ocirc;
if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED)) if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
return 0; return 0;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!CIRCUIT_IS_ORIGIN(circ)) if (!CIRCUIT_IS_ORIGIN(circ))
continue; continue;
ocirc = TO_ORIGIN_CIRCUIT(circ); ocirc = TO_ORIGIN_CIRCUIT(circ);
@ -3926,6 +3925,7 @@ control_event_circ_bandwidth_used(void)
(unsigned long)ocirc->n_written_circ_bw); (unsigned long)ocirc->n_written_circ_bw);
ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0; ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0;
} }
SMARTLIST_FOREACH_END(circ);
return 0; return 0;
} }
@ -4090,14 +4090,13 @@ format_cell_stats(char **event_string, circuit_t *circ,
int int
control_event_circuit_cell_stats(void) control_event_circuit_cell_stats(void)
{ {
circuit_t *circ;
cell_stats_t *cell_stats; cell_stats_t *cell_stats;
char *event_string; char *event_string;
if (!get_options()->TestingEnableCellStatsEvent || if (!get_options()->TestingEnableCellStatsEvent ||
!EVENT_IS_INTERESTING(EVENT_CELL_STATS)) !EVENT_IS_INTERESTING(EVENT_CELL_STATS))
return 0; return 0;
cell_stats = tor_malloc(sizeof(cell_stats_t));; cell_stats = tor_malloc(sizeof(cell_stats_t));;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!circ->testing_cell_stats) if (!circ->testing_cell_stats)
continue; continue;
sum_up_cell_stats_by_command(circ, cell_stats); sum_up_cell_stats_by_command(circ, cell_stats);
@ -4106,6 +4105,7 @@ control_event_circuit_cell_stats(void)
"650 CELL_STATS %s\r\n", event_string); "650 CELL_STATS %s\r\n", event_string);
tor_free(event_string); tor_free(event_string);
} }
SMARTLIST_FOREACH_END(circ);
tor_free(cell_stats); tor_free(cell_stats);
return 0; return 0;
} }

View File

@ -2864,8 +2864,8 @@ typedef struct circuit_t {
/** Unique ID for measuring tunneled network status requests. */ /** Unique ID for measuring tunneled network status requests. */
uint64_t dirreq_id; uint64_t dirreq_id;
/** Next circuit in linked list of all circuits (global_circuitlist). */ /** Index in smartlist of all circuits (global_circuitlist). */
TOR_LIST_ENTRY(circuit_t) head; int global_circuitlist_idx;
/** Next circuit in the doubly-linked ring of circuits waiting to add /** Next circuit in the doubly-linked ring of circuits waiting to add
* cells to n_conn. NULL if we have no cells pending, or if we're not * cells to n_conn. NULL if we have no cells pending, or if we're not

View File

@ -2328,15 +2328,15 @@ packed_cell_free(packed_cell_t *cell)
void void
dump_cell_pool_usage(int severity) dump_cell_pool_usage(int severity)
{ {
circuit_t *c;
int n_circs = 0; int n_circs = 0;
int n_cells = 0; int n_cells = 0;
TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) {
n_cells += c->n_chan_cells.n; n_cells += c->n_chan_cells.n;
if (!CIRCUIT_IS_ORIGIN(c)) if (!CIRCUIT_IS_ORIGIN(c))
n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n; n_cells += TO_OR_CIRCUIT(c)->p_chan_cells.n;
++n_circs; ++n_circs;
} }
SMARTLIST_FOREACH_END(c);
tor_log(severity, LD_MM, tor_log(severity, LD_MM,
"%d cells allocated on %d circuits. %d cells leaked.", "%d cells allocated on %d circuits. %d cells leaked.",
n_cells, n_circs, (int)total_cells_allocated - n_cells); n_cells, n_circs, (int)total_cells_allocated - n_cells);

View File

@ -376,9 +376,8 @@ rend_client_rendcirc_has_opened(origin_circuit_t *circ)
static void static void
rend_client_close_other_intros(const char *onion_address) rend_client_close_other_intros(const char *onion_address)
{ {
circuit_t *c;
/* abort parallel intro circs, if any */ /* abort parallel intro circs, if any */
TOR_LIST_FOREACH(c, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, c) {
if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING || if ((c->purpose == CIRCUIT_PURPOSE_C_INTRODUCING ||
c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) && c->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) &&
!c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) {
@ -393,6 +392,7 @@ rend_client_close_other_intros(const char *onion_address)
} }
} }
} }
SMARTLIST_FOREACH_END(c);
} }
/** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell. /** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell.

View File

@ -524,7 +524,6 @@ rend_config_services(const or_options_t *options, int validate_only)
* other ones. */ * other ones. */
if (old_service_list && !validate_only) { if (old_service_list && !validate_only) {
smartlist_t *surviving_services = smartlist_new(); smartlist_t *surviving_services = smartlist_new();
circuit_t *circ;
/* Copy introduction points to new services. */ /* Copy introduction points to new services. */
/* XXXX This is O(n^2), but it's only called on reconfigure, so it's /* XXXX This is O(n^2), but it's only called on reconfigure, so it's
@ -544,7 +543,7 @@ rend_config_services(const or_options_t *options, int validate_only)
/* XXXX it would be nicer if we had a nicer abstraction to use here, /* XXXX it would be nicer if we had a nicer abstraction to use here,
* so we could just iterate over the list of services to close, but * so we could just iterate over the list of services to close, but
* once again, this isn't critical-path code. */ * once again, this isn't critical-path code. */
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!circ->marked_for_close && if (!circ->marked_for_close &&
circ->state == CIRCUIT_STATE_OPEN && circ->state == CIRCUIT_STATE_OPEN &&
(circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
@ -569,6 +568,7 @@ rend_config_services(const or_options_t *options, int validate_only)
/* XXXX Is there another reason we should use here? */ /* XXXX Is there another reason we should use here? */
} }
} }
SMARTLIST_FOREACH_END(circ);
smartlist_free(surviving_services); smartlist_free(surviving_services);
SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr, SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
rend_service_free(ptr)); rend_service_free(ptr));
@ -2384,8 +2384,7 @@ static int
count_established_intro_points(const char *query) count_established_intro_points(const char *query)
{ {
int num_ipos = 0; int num_ipos = 0;
circuit_t *circ; SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
if (!circ->marked_for_close && if (!circ->marked_for_close &&
circ->state == CIRCUIT_STATE_OPEN && circ->state == CIRCUIT_STATE_OPEN &&
(circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
@ -2396,6 +2395,7 @@ count_established_intro_points(const char *query)
num_ipos++; num_ipos++;
} }
} }
SMARTLIST_FOREACH_END(circ);
return num_ipos; return num_ipos;
} }

View File

@ -2471,7 +2471,6 @@ rep_hist_format_buffer_stats(time_t now)
time_t time_t
rep_hist_buffer_stats_write(time_t now) rep_hist_buffer_stats_write(time_t now)
{ {
circuit_t *circ;
char *str = NULL; char *str = NULL;
if (!start_of_buffer_stats_interval) if (!start_of_buffer_stats_interval)
@ -2480,9 +2479,10 @@ rep_hist_buffer_stats_write(time_t now)
goto done; /* Not ready to write */ goto done; /* Not ready to write */
/* Add open circuits to the history. */ /* Add open circuits to the history. */
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) { SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
rep_hist_buffer_stats_add_circ(circ, now); rep_hist_buffer_stats_add_circ(circ, now);
} }
SMARTLIST_FOREACH_END(circ);
/* Generate history string. */ /* Generate history string. */
str = rep_hist_format_buffer_stats(now); str = rep_hist_format_buffer_stats(now);

View File

@ -28,13 +28,7 @@ static void log_accounting(const time_t now, const or_options_t *options);
STATIC int STATIC int
count_circuits(void) count_circuits(void)
{ {
circuit_t *circ; return smartlist_len(circuit_get_global_list());
int nr=0;
TOR_LIST_FOREACH(circ, circuit_get_global_list(), head)
nr++;
return nr;
} }
/** Take seconds <b>secs</b> and return a newly allocated human-readable /** Take seconds <b>secs</b> and return a newly allocated human-readable

View File

@ -30,27 +30,24 @@
* global circuits. * global circuits.
*/ */
struct global_circuitlist_s mock_global_circuitlist = static smartlist_t * mock_global_circuitlist = NULL;
TOR_LIST_HEAD_INITIALIZER(global_circuitlist);
NS_DECL(struct global_circuitlist_s *, circuit_get_global_list, (void)); NS_DECL(smartlist_t *, circuit_get_global_list, (void));
static void static void
NS(test_main)(void *arg) NS(test_main)(void *arg)
{ {
/* Choose origin_circuit_t wlog. */ /* Choose origin_circuit_t wlog. */
origin_circuit_t *mock_circuit1, *mock_circuit2; origin_circuit_t *mock_circuit1, *mock_circuit2;
circuit_t *circ, *tmp;
int expected_circuits = 2, actual_circuits; int expected_circuits = 2, actual_circuits;
(void)arg; (void)arg;
mock_circuit1 = tor_malloc_zero(sizeof(origin_circuit_t)); mock_circuit1 = tor_malloc_zero(sizeof(origin_circuit_t));
mock_circuit2 = tor_malloc_zero(sizeof(origin_circuit_t)); mock_circuit2 = tor_malloc_zero(sizeof(origin_circuit_t));
TOR_LIST_INSERT_HEAD( mock_global_circuitlist = smartlist_new();
&mock_global_circuitlist, TO_CIRCUIT(mock_circuit1), head); smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit1));
TOR_LIST_INSERT_HEAD( smartlist_add(mock_global_circuitlist, TO_CIRCUIT(mock_circuit2));
&mock_global_circuitlist, TO_CIRCUIT(mock_circuit2), head);
NS_MOCK(circuit_get_global_list); NS_MOCK(circuit_get_global_list);
@ -59,16 +56,17 @@ NS(test_main)(void *arg)
tt_assert(expected_circuits == actual_circuits); tt_assert(expected_circuits == actual_circuits);
done: done:
TOR_LIST_FOREACH_SAFE( tor_free(mock_circuit1);
circ, NS(circuit_get_global_list)(), head, tmp); tor_free(mock_circuit2);
tor_free(circ); smartlist_free(mock_global_circuitlist);
mock_global_circuitlist = NULL;
NS_UNMOCK(circuit_get_global_list); NS_UNMOCK(circuit_get_global_list);
} }
static struct global_circuitlist_s * static smartlist_t *
NS(circuit_get_global_list)(void) NS(circuit_get_global_list)(void)
{ {
return &mock_global_circuitlist; return mock_global_circuitlist;
} }
#undef NS_SUBMODULE #undef NS_SUBMODULE