diff options
author | Nick Mathewson <nickm@torproject.org> | 2011-05-12 11:10:35 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2011-05-12 11:10:35 -0400 |
commit | 4ba9f3e31702020eaa336ccb33294568cda256eb (patch) | |
tree | 4bb95303e56a37dc624ef6834886929dfce0ecfe /src/or/nodelist.c | |
parent | 3968e8d14b7f6282963223b0fd4f4ca3afb60c61 (diff) | |
download | tor-4ba9f3e31702020eaa336ccb33294568cda256eb.tar.gz tor-4ba9f3e31702020eaa336ccb33294568cda256eb.zip |
Track where microdescs are referenced to prevent free errs
On IRC, wanoskarnet notes that if we ever do microdesc_free() on a
microdesc that's in the nodelist, we're in trouble. Also, we're in
trouble if we free one that's still in the microdesc_cache map.
This code adds a flag to microdesc_t to note where the microdesc is
referenced from, and checks those flags from microdesc_free(). I
don't believe we have any errors here now, but if we introduce some
later, let's log and recover from them rather than introducing
heisenbugs later on.
Addresses bug 3153.
Diffstat (limited to 'src/or/nodelist.c')
-rw-r--r-- | src/or/nodelist.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/or/nodelist.c b/src/or/nodelist.c index a736dc3b8c..29bd7e0d9b 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -158,8 +158,12 @@ nodelist_add_microdesc(microdesc_t *md) if (rs == NULL) return NULL; node = node_get_mutable_by_id(rs->identity_digest); - if (node) + if (node) { + if (node->md) + node->md->held_by_node = 0; node->md = md; + md->held_by_node = 1; + } return node; } @@ -184,8 +188,12 @@ nodelist_set_consensus(networkstatus_t *ns) if (ns->flavor == FLAV_MICRODESC) { if (node->md == NULL || 0!=memcmp(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) { + if (node->md) + node->md->held_by_node = 0; node->md = microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest); + if (node->md) + node->md->held_by_node = 1; } } @@ -240,8 +248,10 @@ void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md) { node_t *node = node_get_mutable_by_id(identity_digest); - if (node && node->md == md) + if (node && node->md == md) { node->md = NULL; + md->held_by_node = 0; + } } /** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */ @@ -288,6 +298,8 @@ node_free(node_t *node) { if (!node) return; + if (node->md) + node->md->held_by_node = 0; tor_assert(node->nodelist_idx == -1); tor_free(node); } @@ -373,6 +385,8 @@ nodelist_assert_ok(void) microdesc_t *md = microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest); tor_assert(md == node->md); + if (md) + tor_assert(md->held_by_node == 1); } } SMARTLIST_FOREACH_END(rs); } |