From ae04b80fe197118d52a2b7eb947154be1a9d0710 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 17 Dec 2014 02:44:27 +0000 Subject: [PATCH] cancel non-critical DNS lookups when shutting down, to cut down on shutdown delay --- ChangeLog | 2 ++ include/libtorrent/resolver.hpp | 7 +++++++ include/libtorrent/resolver_interface.hpp | 18 +++++++++++++----- src/http_tracker_connection.cpp | 2 +- src/resolver.cpp | 18 ++++++++++++++++-- src/session_impl.cpp | 8 +++++++- src/torrent.cpp | 14 +++++++------- src/udp_socket.cpp | 2 ++ src/udp_tracker_connection.cpp | 2 +- 9 files changed, 56 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5a6d8762..423d91665 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * cancel non-critical DNS lookups when shutting down, to cut down on + shutdown delay. * greatly simplify the debug logging infrastructure. logs are now delivered as alerts, and log level is controlled by the alert mask. * removed auto_expand_choker. use rate_based_choker instead diff --git a/include/libtorrent/resolver.hpp b/include/libtorrent/resolver.hpp index 515e42dd5..caad09c39 100644 --- a/include/libtorrent/resolver.hpp +++ b/include/libtorrent/resolver.hpp @@ -53,6 +53,8 @@ struct TORRENT_EXTRA_EXPORT resolver : resolver_interface void async_resolve(std::string const& host, int flags , callback_t const& h); + void abort(); + private: void on_lookup(error_code const& ec, tcp::resolver::iterator i @@ -67,8 +69,13 @@ private: typedef boost::unordered_map cache_t; cache_t m_cache; io_service& m_ios; + + // all lookups in this resolver are aborted on shutdown. tcp::resolver m_resolver; + // lookups in this resolver are not aborted on shutdown + tcp::resolver m_critical_resolver; + // max number of cached entries int m_max_size; diff --git a/include/libtorrent/resolver_interface.hpp b/include/libtorrent/resolver_interface.hpp index d55322d5d..70a6bd916 100644 --- a/include/libtorrent/resolver_interface.hpp +++ b/include/libtorrent/resolver_interface.hpp @@ -48,14 +48,22 @@ struct resolver_interface typedef boost::function const&)> callback_t; - // prefer_cache will always use the cache if we have - // an entry, regardless of how old it is. This is usefull - // when completing the lookup quickly is more important - // than accuracy - enum flags_t { prefer_cache = 1 }; + enum flags_t + { + // this flag will make async_resolve() always use the cache if we have an + // entry, regardless of how old it is. This is usefull when completing the + // lookup quickly is more important than accuracy + prefer_cache = 1, + + // set this flag for lookups that are not critical during shutdown. i.e. + // for looking up tracker names _except_ when stopping a tracker. + abort_on_shutdown = 2 + }; virtual void async_resolve(std::string const& host, int flags , callback_t const& h) = 0; + + virtual void abort() = 0; }; } diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index da99c52d0..87cc9dc28 100644 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -231,7 +231,7 @@ namespace libtorrent , bind_interface() , tracker_req().event == tracker_request::stopped ? resolver_interface::prefer_cache - : 0 + : resolver_interface::abort_on_shutdown #if TORRENT_USE_I2P , m_i2p_conn #endif diff --git a/src/resolver.cpp b/src/resolver.cpp index 6b1d4a6a0..246dbe4c0 100644 --- a/src/resolver.cpp +++ b/src/resolver.cpp @@ -39,6 +39,7 @@ namespace libtorrent resolver::resolver(io_service& ios) : m_ios(ios) , m_resolver(ios) + , m_critical_resolver(ios) , m_max_size(700) , m_timeout(seconds(1200)) {} @@ -108,8 +109,21 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("resolver::on_lookup"); #endif - m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2 - , h, host)); + if (flags & resolver_interface::abort_on_shutdown) + { + m_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2 + , h, host)); + } + else + { + m_critical_resolver.async_resolve(q, boost::bind(&resolver::on_lookup, this, _1, _2 + , h, host)); + } + } + + void resolver::abort() + { + m_resolver.cancel(); } } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 470c55b50..620adbe88 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -979,6 +979,12 @@ namespace aux { #if defined TORRENT_LOGGING session_log(" *** ABORT CALLED ***"); #endif + + // this will cancel requests that are not critical for shutting down + // cleanly. i.e. essentially tracker hostname lookups that we're not + // about to send event=stopped to + m_host_resolver.abort(); + // abort the main thread m_abort = true; error_code ec; @@ -5340,7 +5346,7 @@ retry: #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("session_impl::on_dht_router_name_lookup"); #endif - m_host_resolver.async_resolve(node.first, 0 + m_host_resolver.async_resolve(node.first, resolver_interface::abort_on_shutdown , boost::bind(&session_impl::on_dht_router_name_lookup , this, _1, _2, node.second)); } diff --git a/src/torrent.cpp b/src/torrent.cpp index 6ceaf22e8..b3be45aa6 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3236,7 +3236,7 @@ namespace libtorrent #if defined TORRENT_ASIO_DEBUGGING add_outstanding_async("torrent::on_peer_name_lookup"); #endif - m_ses.async_resolve(i->hostname, 0 + m_ses.async_resolve(i->hostname, resolver_interface::abort_on_shutdown , boost::bind(&torrent::on_peer_name_lookup , shared_from_this(), _1, _2, i->port)); } @@ -5990,7 +5990,7 @@ namespace libtorrent // use proxy web->resolving = true; - m_ses.async_resolve(ps.hostname, 0 + m_ses.async_resolve(ps.hostname, resolver_interface::abort_on_shutdown , boost::bind(&torrent::on_proxy_name_lookup, shared_from_this() , _1, _2, web, ps.port)); } @@ -6007,8 +6007,8 @@ namespace libtorrent #endif web->resolving = true; - m_ses.async_resolve(hostname, 0, boost::bind( - &torrent::on_name_lookup, shared_from_this(), _1, _2 + m_ses.async_resolve(hostname, resolver_interface::abort_on_shutdown + , boost::bind(&torrent::on_name_lookup, shared_from_this(), _1, _2 , port, web, tcp::endpoint())); } } @@ -6091,8 +6091,8 @@ namespace libtorrent } web->resolving = true; - m_ses.async_resolve(hostname, 0, boost::bind( - &torrent::on_name_lookup, shared_from_this(), _1, _2 + m_ses.async_resolve(hostname, resolver_interface::abort_on_shutdown + , boost::bind(&torrent::on_name_lookup, shared_from_this(), _1, _2 , port, web, a)); } @@ -6368,7 +6368,7 @@ namespace libtorrent return; } m_resolving_country = true; - m_ses.async_resolve(hostname, 0 + m_ses.async_resolve(hostname, resolver_interface::abort_on_shutdown , boost::bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)); } diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index fbc6b9f9a..9500e9d25 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -773,6 +773,8 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps) { m_queue_packets = true; // connect to socks5 server and open up the UDP tunnel + + // TODO: use the system resolver_interface here tcp::resolver::query q(ps.hostname, to_string(ps.port).elems); ++m_outstanding_ops; #if TORRENT_USE_ASSERTS diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 0c52e6691..55234d7a0 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -120,7 +120,7 @@ namespace libtorrent m_man.host_resolver().async_resolve(hostname , tracker_req().event == tracker_request::stopped ? resolver_interface::prefer_cache - : 0 + : resolver_interface::abort_on_shutdown , boost::bind(&udp_tracker_connection::name_lookup , shared_from_this(), _1, _2, port));