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
This commit is contained in:
Steven Siloti 2015-11-16 21:05:32 -08:00
parent 0dbe94616a
commit 86116caf4c
1 changed files with 13 additions and 1 deletions

View File

@ -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);
}
}