From 86116caf4c6d98a68fae48514b9fbe4aa79b118a Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Mon, 16 Nov 2015 21:05:32 -0800 Subject: [PATCH] fix assert after a DHT get/put request If an observer is abandoned due to there being more than 100 results in a traversal then the traversal may complete while the observer is still outstanding. When the observer times out or is aborted it calls traversal_algorithm::failed() which asserts because m_invoke_count has been cleared to zero by traversal_algorithm::done(). To fix this add a check when abandoning observers to see if they have an outstanding query. If they do then flag them as done to prevent them from calling back into the traversal and decrement the invoke count. Fixes #271 --- src/kademlia/traversal_algorithm.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/kademlia/traversal_algorithm.cpp b/src/kademlia/traversal_algorithm.cpp index 02cb42a96..4f8e5b69f 100644 --- a/src/kademlia/traversal_algorithm.cpp +++ b/src/kademlia/traversal_algorithm.cpp @@ -218,10 +218,22 @@ void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsig if (m_results.size() > 100) { -#if TORRENT_USE_ASSERTS for (int i = 100; i < int(m_results.size()); ++i) + { + if ((m_results[i]->flags & (observer::flag_queried | observer::flag_failed | observer::flag_alive)) + == observer::flag_queried) + { + // set the done flag on any outstanding queries to prevent them from + // calling finished() or failed() + m_results[i]->flags |= observer::flag_done; + TORRENT_ASSERT(m_invoke_count > 0); + --m_invoke_count; + } + +#if TORRENT_USE_ASSERTS m_results[i]->m_was_abandoned = true; #endif + } m_results.resize(100); } }