fix traversal_algorithm::done() being invoked more than once
A traversal can be done while there are still outstanding queries (i.e. m_invoke_count is non-zero) if K good responses have already been received and none of the outstanding queries are closer than the nodes which have responded. When this happens and the outstanding queries eventually complete or timeout they call traversal_algorithm::failed() or traversal_algorithm::finished() as usual which will cause traversal_algorithm::done() to be called yet again. The fix is to always set the done flag on all queried observers in traversal_algorithm::done() so that the observers will refrain from calling back into the traversal. This also makes traversal_algorithm::abort() redundant since this was the only thing it did before it called into done().
This commit is contained in:
parent
0c435b42b2
commit
c2277b3ea5
|
@ -67,7 +67,6 @@ struct traversal_algorithm : boost::noncopyable
|
|||
void failed(observer_ptr o, int flags = 0);
|
||||
virtual ~traversal_algorithm();
|
||||
void status(dht_lookup& l);
|
||||
void abort();
|
||||
|
||||
void* allocate_observer();
|
||||
void free_observer(void* ptr);
|
||||
|
|
|
@ -135,8 +135,6 @@ char const* find_data::name() const { return "find_data"; }
|
|||
|
||||
void find_data::done()
|
||||
{
|
||||
if (m_invoke_count != 0) return;
|
||||
|
||||
m_done = true;
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
|
|
@ -111,7 +111,7 @@ void get_item::got_data(bdecode_node const& v,
|
|||
// There can only be one true immutable item with a given id
|
||||
// Now that we've got it and the user doesn't want to do a put
|
||||
// there's no point in continuing to query other nodes
|
||||
abort();
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -374,14 +374,22 @@ void traversal_algorithm::done()
|
|||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
int results_target = m_node.m_table.bucket_size();
|
||||
int closest_target = 160;
|
||||
#endif
|
||||
|
||||
// TODO: 3 it would be nice to not have to perform this loop if
|
||||
// logging is disabled
|
||||
for (std::vector<observer_ptr>::iterator i = m_results.begin()
|
||||
, end(m_results.end()); i != end && results_target > 0; ++i)
|
||||
, end(m_results.end()); i != end; ++i)
|
||||
{
|
||||
boost::intrusive_ptr<observer> o = *i;
|
||||
if ((o->flags & observer::flag_alive) && get_node().observer())
|
||||
if (o->flags & observer::flag_queried)
|
||||
{
|
||||
// set the done flag on any outstanding queries to prevent them from
|
||||
// calling finished() or failed() after we've already declared the traversal
|
||||
// done
|
||||
o->flags |= observer::flag_done;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (results_target > 0 && (o->flags & observer::flag_alive) && get_node().observer())
|
||||
{
|
||||
TORRENT_ASSERT(o->flags & observer::flag_queried);
|
||||
char hex_id[41];
|
||||
|
@ -395,8 +403,10 @@ void traversal_algorithm::done()
|
|||
int dist = distance_exp(m_target, o->id());
|
||||
if (dist < closest_target) closest_target = dist;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (get_node().observer())
|
||||
{
|
||||
get_node().observer()->log(dht_logger::traversal
|
||||
|
@ -404,9 +414,11 @@ void traversal_algorithm::done()
|
|||
, static_cast<void*>(this), closest_target, name());
|
||||
}
|
||||
#endif
|
||||
|
||||
// delete all our references to the observer objects so
|
||||
// they will in turn release the traversal algorithm
|
||||
m_results.clear();
|
||||
m_invoke_count = 0;
|
||||
}
|
||||
|
||||
bool traversal_algorithm::add_requests()
|
||||
|
@ -610,26 +622,5 @@ void traversal_observer::reply(msg const& m)
|
|||
set_id(node_id(id.string_ptr()));
|
||||
}
|
||||
|
||||
void traversal_algorithm::abort()
|
||||
{
|
||||
for (std::vector<observer_ptr>::iterator i = m_results.begin()
|
||||
, end(m_results.end()); i != end; ++i)
|
||||
{
|
||||
observer& o = **i;
|
||||
if (o.flags & observer::flag_queried)
|
||||
o.flags |= observer::flag_done;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
if (get_node().observer())
|
||||
{
|
||||
get_node().observer()->log(dht_logger::traversal, "[%p] ABORTED type: %s"
|
||||
, static_cast<void*>(this), name());
|
||||
}
|
||||
#endif
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
} } // namespace libtorrent::dht
|
||||
|
||||
|
|
Loading…
Reference in New Issue