fix for crashes when stopping or restarting DHT
This commit is contained in:
parent
fcc9c49608
commit
7888b72e12
|
@ -363,7 +363,7 @@ namespace libtorrent
|
||||||
boost::posix_time::ptime m_last_tick;
|
boost::posix_time::ptime m_last_tick;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#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;
|
dht_settings m_dht_settings;
|
||||||
#endif
|
#endif
|
||||||
// the timer used to fire the second_tick
|
// the timer used to fire the second_tick
|
||||||
|
|
|
@ -45,6 +45,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/filesystem/operations.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.hpp"
|
||||||
#include "libtorrent/kademlia/node_id.hpp"
|
#include "libtorrent/kademlia/node_id.hpp"
|
||||||
|
@ -60,10 +62,18 @@ namespace libtorrent { namespace dht
|
||||||
TORRENT_DECLARE_LOG(dht_tracker);
|
TORRENT_DECLARE_LOG(dht_tracker);
|
||||||
#endif
|
#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
|
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
|
dht_tracker(asio::io_service& ios, dht_settings const& settings
|
||||||
, asio::ip::address listen_interface, entry const& bootstrap);
|
, asio::ip::address listen_interface, entry const& bootstrap);
|
||||||
|
void stop();
|
||||||
|
|
||||||
void add_node(udp::endpoint node);
|
void add_node(udp::endpoint node);
|
||||||
void add_node(std::pair<std::string, int> const& 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);
|
void dht_status(session_status& s);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
boost::intrusive_ptr<dht_tracker> self()
|
||||||
|
{ return boost::intrusive_ptr<dht_tracker>(this); }
|
||||||
|
|
||||||
void on_name_lookup(asio::error_code const& e
|
void on_name_lookup(asio::error_code const& e
|
||||||
, udp::resolver::iterator host);
|
, udp::resolver::iterator host);
|
||||||
|
@ -116,6 +129,9 @@ namespace libtorrent { namespace dht
|
||||||
|
|
||||||
// used to resolve hostnames for nodes
|
// used to resolve hostnames for nodes
|
||||||
udp::resolver m_host_resolver;
|
udp::resolver m_host_resolver;
|
||||||
|
|
||||||
|
// reference counter for intrusive_ptr
|
||||||
|
mutable boost::detail::atomic_count m_refs;
|
||||||
|
|
||||||
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
int m_replies_sent[5];
|
int m_replies_sent[5];
|
||||||
|
|
|
@ -126,6 +126,22 @@ namespace
|
||||||
|
|
||||||
namespace libtorrent { namespace dht
|
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
|
#ifdef TORRENT_DHT_VERBOSE_LOGGING
|
||||||
TORRENT_DEFINE_LOG(dht_tracker)
|
TORRENT_DEFINE_LOG(dht_tracker)
|
||||||
#endif
|
#endif
|
||||||
|
@ -146,6 +162,7 @@ namespace libtorrent { namespace dht
|
||||||
, m_settings(settings)
|
, m_settings(settings)
|
||||||
, m_refresh_bucket(160)
|
, m_refresh_bucket(160)
|
||||||
, m_host_resolver(ios)
|
, m_host_resolver(ios)
|
||||||
|
, m_refs(0)
|
||||||
{
|
{
|
||||||
using boost::bind;
|
using boost::bind;
|
||||||
|
|
||||||
|
@ -187,20 +204,28 @@ namespace libtorrent { namespace dht
|
||||||
} catch (std::exception&) {}
|
} 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_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
|
||||||
, m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer]
|
, 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.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.expires_from_now(seconds(10));
|
||||||
m_connection_timer.async_wait(m_strand.wrap(
|
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.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)
|
void dht_tracker::dht_status(session_status& s)
|
||||||
|
@ -215,7 +240,7 @@ namespace libtorrent { namespace dht
|
||||||
if (e) return;
|
if (e) return;
|
||||||
time_duration d = m_dht.connection_timeout();
|
time_duration d = m_dht.connection_timeout();
|
||||||
m_connection_timer.expires_from_now(d);
|
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)
|
catch (std::exception& exc)
|
||||||
{
|
{
|
||||||
|
@ -233,7 +258,7 @@ namespace libtorrent { namespace dht
|
||||||
time_duration d = m_dht.refresh_timeout();
|
time_duration d = m_dht.refresh_timeout();
|
||||||
m_refresh_timer.expires_from_now(d);
|
m_refresh_timer.expires_from_now(d);
|
||||||
m_refresh_timer.async_wait(m_strand.wrap(
|
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&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
|
@ -361,7 +386,7 @@ namespace libtorrent { namespace dht
|
||||||
m_buffer = (m_buffer + 1) & 1;
|
m_buffer = (m_buffer + 1) & 1;
|
||||||
m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
|
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_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;
|
if (error) return;
|
||||||
|
|
||||||
|
@ -655,7 +680,7 @@ namespace libtorrent { namespace dht
|
||||||
{
|
{
|
||||||
udp::resolver::query q(node.first, lexical_cast<std::string>(node.second));
|
udp::resolver::query q(node.first, lexical_cast<std::string>(node.second));
|
||||||
m_host_resolver.async_resolve(q, m_strand.wrap(
|
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
|
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));
|
udp::resolver::query q(node.first, lexical_cast<std::string>(node.second));
|
||||||
m_host_resolver.async_resolve(q, m_strand.wrap(
|
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
|
void dht_tracker::on_router_name_lookup(asio::error_code const& e
|
||||||
|
|
|
@ -1507,7 +1507,11 @@ namespace libtorrent { namespace detail
|
||||||
void session_impl::start_dht(entry const& startup_state)
|
void session_impl::start_dht(entry const& startup_state)
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
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.reset(new dht::dht_tracker(m_io_service
|
||||||
, m_dht_settings, m_listen_interface.address()
|
, m_dht_settings, m_listen_interface.address()
|
||||||
, startup_state));
|
, startup_state));
|
||||||
|
@ -1516,6 +1520,7 @@ namespace libtorrent { namespace detail
|
||||||
void session_impl::stop_dht()
|
void session_impl::stop_dht()
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
|
m_dht->stop();
|
||||||
m_dht.reset();
|
m_dht.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -420,9 +420,11 @@ namespace libtorrent
|
||||||
if (m_pimpl->info.num_files() == 1)
|
if (m_pimpl->info.num_files() == 1)
|
||||||
{
|
{
|
||||||
path single_file = m_pimpl->info.begin_files()->path;
|
path single_file = m_pimpl->info.begin_files()->path;
|
||||||
|
assert(!is_complete(single_file));
|
||||||
if (single_file.has_branch_path())
|
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;
|
old_path = m_pimpl->save_path / trunk;
|
||||||
new_path = save_path / trunk;
|
new_path = save_path / trunk;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue