From 7888b72e12a67b777e597ed844429b68204779e6 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 25 Feb 2007 09:42:43 +0000 Subject: [PATCH] fix for crashes when stopping or restarting DHT --- include/libtorrent/aux_/session_impl.hpp | 2 +- include/libtorrent/kademlia/dht_tracker.hpp | 16 ++++++++ src/kademlia/dht_tracker.cpp | 45 ++++++++++++++++----- src/session_impl.cpp | 7 +++- src/storage.cpp | 4 +- 5 files changed, 61 insertions(+), 13 deletions(-) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index f924bf67c..ff4d2980b 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -363,7 +363,7 @@ namespace libtorrent boost::posix_time::ptime m_last_tick; #ifndef TORRENT_DISABLE_DHT - boost::scoped_ptr m_dht; + boost::shared_ptr m_dht; dht_settings m_dht_settings; #endif // the timer used to fire the second_tick diff --git a/include/libtorrent/kademlia/dht_tracker.hpp b/include/libtorrent/kademlia/dht_tracker.hpp index 997e58a2a..d52c24fd8 100644 --- a/include/libtorrent/kademlia/dht_tracker.hpp +++ b/include/libtorrent/kademlia/dht_tracker.hpp @@ -45,6 +45,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #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 const& node); @@ -80,6 +90,9 @@ namespace libtorrent { namespace dht void dht_status(session_status& s); private: + + boost::intrusive_ptr self() + { return boost::intrusive_ptr(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]; diff --git a/src/kademlia/dht_tracker.cpp b/src/kademlia/dht_tracker.cpp index f3af64994..4de0cce55 100644 --- a/src/kademlia/dht_tracker.cpp +++ b/src/kademlia/dht_tracker.cpp @@ -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(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(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 diff --git a/src/session_impl.cpp b/src/session_impl.cpp index f292362f4..65c0f25c9 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -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(); } diff --git a/src/storage.cpp b/src/storage.cpp index 3d294c5a5..b25be79ca 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -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; }