fix for crashes when stopping or restarting DHT

This commit is contained in:
Arvid Norberg 2007-02-25 09:42:43 +00:00
parent fcc9c49608
commit 7888b72e12
5 changed files with 61 additions and 13 deletions

View File

@ -363,7 +363,7 @@ namespace libtorrent
boost::posix_time::ptime m_last_tick;
#ifndef TORRENT_DISABLE_DHT
boost::scoped_ptr<dht::dht_tracker> m_dht;
boost::shared_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings;
#endif
// the timer used to fire the second_tick

View File

@ -45,6 +45,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/detail/atomic_count.hpp>
#include "libtorrent/kademlia/node.hpp"
#include "libtorrent/kademlia/node_id.hpp"
@ -60,10 +62,18 @@ namespace libtorrent { namespace dht
TORRENT_DECLARE_LOG(dht_tracker);
#endif
struct dht_tracker;
TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*);
TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*);
struct dht_tracker
{
friend void intrusive_ptr_add_ref(dht_tracker const*);
friend void intrusive_ptr_release(dht_tracker const*);
dht_tracker(asio::io_service& ios, dht_settings const& settings
, asio::ip::address listen_interface, entry const& bootstrap);
void stop();
void add_node(udp::endpoint node);
void add_node(std::pair<std::string, int> const& node);
@ -80,6 +90,9 @@ namespace libtorrent { namespace dht
void dht_status(session_status& s);
private:
boost::intrusive_ptr<dht_tracker> self()
{ return boost::intrusive_ptr<dht_tracker>(this); }
void on_name_lookup(asio::error_code const& e
, udp::resolver::iterator host);
@ -116,6 +129,9 @@ namespace libtorrent { namespace dht
// used to resolve hostnames for nodes
udp::resolver m_host_resolver;
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
int m_replies_sent[5];

View File

@ -126,6 +126,22 @@ namespace
namespace libtorrent { namespace dht
{
void intrusive_ptr_add_ref(dht_tracker const* c)
{
assert(c->m_refs >= 0);
assert(c != 0);
++c->m_refs;
}
void intrusive_ptr_release(dht_tracker const* c)
{
assert(c->m_refs > 0);
assert(c != 0);
if (--c->m_refs == 0)
delete c;
}
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DEFINE_LOG(dht_tracker)
#endif
@ -146,6 +162,7 @@ namespace libtorrent { namespace dht
, m_settings(settings)
, m_refresh_bucket(160)
, m_host_resolver(ios)
, m_refs(0)
{
using boost::bind;
@ -187,20 +204,28 @@ namespace libtorrent { namespace dht
} catch (std::exception&) {}
}
m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, this));
m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self()));
m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
, m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer]
, m_strand.wrap(bind(&dht_tracker::on_receive, this, _1, _2)));
, m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2)));
m_timer.expires_from_now(seconds(1));
m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, this, _1)));
m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1)));
m_connection_timer.expires_from_now(seconds(10));
m_connection_timer.async_wait(m_strand.wrap(
bind(&dht_tracker::connection_timeout, this, _1)));
bind(&dht_tracker::connection_timeout, self(), _1)));
m_refresh_timer.expires_from_now(minutes(15));
m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, this, _1)));
m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1)));
}
void dht_tracker::stop()
{
m_timer.cancel();
m_connection_timer.cancel();
m_refresh_timer.cancel();
m_socket.close();
}
void dht_tracker::dht_status(session_status& s)
@ -215,7 +240,7 @@ namespace libtorrent { namespace dht
if (e) return;
time_duration d = m_dht.connection_timeout();
m_connection_timer.expires_from_now(d);
m_connection_timer.async_wait(m_strand.wrap(bind(&dht_tracker::connection_timeout, this, _1)));
m_connection_timer.async_wait(m_strand.wrap(bind(&dht_tracker::connection_timeout, self(), _1)));
}
catch (std::exception& exc)
{
@ -233,7 +258,7 @@ namespace libtorrent { namespace dht
time_duration d = m_dht.refresh_timeout();
m_refresh_timer.expires_from_now(d);
m_refresh_timer.async_wait(m_strand.wrap(
bind(&dht_tracker::refresh_timeout, this, _1)));
bind(&dht_tracker::refresh_timeout, self(), _1)));
}
catch (std::exception&)
{
@ -361,7 +386,7 @@ namespace libtorrent { namespace dht
m_buffer = (m_buffer + 1) & 1;
m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
, m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer]
, m_strand.wrap(bind(&dht_tracker::on_receive, this, _1, _2)));
, m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2)));
if (error) return;
@ -655,7 +680,7 @@ namespace libtorrent { namespace dht
{
udp::resolver::query q(node.first, lexical_cast<std::string>(node.second));
m_host_resolver.async_resolve(q, m_strand.wrap(
bind(&dht_tracker::on_name_lookup, this, _1, _2)));
bind(&dht_tracker::on_name_lookup, self(), _1, _2)));
}
void dht_tracker::on_name_lookup(asio::error_code const& e
@ -673,7 +698,7 @@ namespace libtorrent { namespace dht
{
udp::resolver::query q(node.first, lexical_cast<std::string>(node.second));
m_host_resolver.async_resolve(q, m_strand.wrap(
bind(&dht_tracker::on_router_name_lookup, this, _1, _2)));
bind(&dht_tracker::on_router_name_lookup, self(), _1, _2)));
}
void dht_tracker::on_router_name_lookup(asio::error_code const& e

View File

@ -1507,7 +1507,11 @@ namespace libtorrent { namespace detail
void session_impl::start_dht(entry const& startup_state)
{
mutex_t::scoped_lock l(m_mutex);
m_dht.reset();
if (m_dht)
{
m_dht->stop();
m_dht.reset();
}
m_dht.reset(new dht::dht_tracker(m_io_service
, m_dht_settings, m_listen_interface.address()
, startup_state));
@ -1516,6 +1520,7 @@ namespace libtorrent { namespace detail
void session_impl::stop_dht()
{
mutex_t::scoped_lock l(m_mutex);
m_dht->stop();
m_dht.reset();
}

View File

@ -420,9 +420,11 @@ namespace libtorrent
if (m_pimpl->info.num_files() == 1)
{
path single_file = m_pimpl->info.begin_files()->path;
assert(!is_complete(single_file));
if (single_file.has_branch_path())
{
std::string const& trunk = *single_file.begin();
assert(single_file.begin() != single_file.end());
std::string trunk = *single_file.begin();
old_path = m_pimpl->save_path / trunk;
new_path = save_path / trunk;
}