From 8f07edbed2d44686b936a3fd3cddc4e5d49d61dc Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 26 Oct 2007 07:14:19 +0000 Subject: [PATCH] asio handlers are now properly cancelled when destructing the session object, race conditions are avoided by waiting for the io service to complete all tasks --- include/libtorrent/aux_/session_impl.hpp | 14 ++++---- include/libtorrent/connection_queue.hpp | 1 + .../libtorrent/http_tracker_connection.hpp | 2 ++ include/libtorrent/tracker_manager.hpp | 2 +- include/libtorrent/udp_tracker_connection.hpp | 2 ++ src/connection_queue.cpp | 5 +++ src/http_tracker_connection.cpp | 17 +++++++-- src/session_impl.cpp | 36 ++++++++++--------- src/torrent.cpp | 2 +- src/tracker_manager.cpp | 12 ++++--- src/udp_tracker_connection.cpp | 18 ++++++++-- 11 files changed, 77 insertions(+), 34 deletions(-) diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index bff8e3387..3f3607191 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -375,12 +375,6 @@ namespace libtorrent // buffers from. boost::pool<> m_send_buffers; - // this is where all active sockets are stored. - // the selector can sleep while there's no activity on - // them - io_service m_io_service; - asio::strand m_strand; - // the file pool that all storages in this session's // torrents uses. It sets a limit on the number of // open files by this session. @@ -395,6 +389,12 @@ namespace libtorrent // object. disk_io_thread m_disk_thread; + // this is where all active sockets are stored. + // the selector can sleep while there's no activity on + // them + io_service m_io_service; + asio::strand m_strand; + // this is a list of half-open tcp connections // (only outgoing connections) // this has to be one of the last @@ -646,7 +646,7 @@ namespace libtorrent void debug_log(const std::string& line) { - (*m_ses.m_logger) << line << "\n"; + (*m_ses.m_logger) << time_now_string() << " " << line << "\n"; } session_impl& m_ses; }; diff --git a/include/libtorrent/connection_queue.hpp b/include/libtorrent/connection_queue.hpp index b3b7cde86..c229ec217 100644 --- a/include/libtorrent/connection_queue.hpp +++ b/include/libtorrent/connection_queue.hpp @@ -56,6 +56,7 @@ public: void done(int ticket); void limit(int limit); int limit() const; + void close(); #ifndef NDEBUG diff --git a/include/libtorrent/http_tracker_connection.hpp b/include/libtorrent/http_tracker_connection.hpp index 5b618c876..c0057dfa1 100755 --- a/include/libtorrent/http_tracker_connection.hpp +++ b/include/libtorrent/http_tracker_connection.hpp @@ -130,6 +130,8 @@ namespace libtorrent , proxy_settings const& ps , std::string const& password = ""); + void close(); + private: boost::intrusive_ptr self() diff --git a/include/libtorrent/tracker_manager.hpp b/include/libtorrent/tracker_manager.hpp index 07c377a0f..2c9ceeaef 100755 --- a/include/libtorrent/tracker_manager.hpp +++ b/include/libtorrent/tracker_manager.hpp @@ -202,7 +202,7 @@ namespace libtorrent void fail(int code, char const* msg); void fail_timeout(); - void close(); + virtual void close(); address const& bind_interface() const { return m_bind_interface; } protected: diff --git a/include/libtorrent/udp_tracker_connection.hpp b/include/libtorrent/udp_tracker_connection.hpp index e5eadc144..4fba505a4 100755 --- a/include/libtorrent/udp_tracker_connection.hpp +++ b/include/libtorrent/udp_tracker_connection.hpp @@ -74,6 +74,8 @@ namespace libtorrent , boost::weak_ptr c , session_settings const& stn); + void close(); + private: enum action_t diff --git a/src/connection_queue.cpp b/src/connection_queue.cpp index 1caeb99fc..c204b5a34 100644 --- a/src/connection_queue.cpp +++ b/src/connection_queue.cpp @@ -86,6 +86,11 @@ namespace libtorrent try_connect(); } + void connection_queue::close() + { + m_timer.cancel(); + } + void connection_queue::limit(int limit) { m_half_open_limit = limit; } diff --git a/src/http_tracker_connection.cpp b/src/http_tracker_connection.cpp index ccca58226..a5c542b44 100755 --- a/src/http_tracker_connection.cpp +++ b/src/http_tracker_connection.cpp @@ -489,7 +489,9 @@ namespace libtorrent , boost::lexical_cast(m_port)); m_name_lookup.async_resolve(q, m_strand.wrap( boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2))); - set_timeout(m_settings.tracker_completion_timeout + set_timeout(req.event == tracker_request::stopped + ? m_settings.stop_tracker_timeout + : m_settings.tracker_completion_timeout , m_settings.tracker_receive_timeout); } @@ -503,6 +505,17 @@ namespace libtorrent fail_timeout(); } + void http_tracker_connection::close() + { + asio::error_code ec; + m_socket.close(ec); + m_name_lookup.cancel(); + if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); + m_connection_ticket = -1; + m_timed_out = true; + tracker_connection::close(); + } + void http_tracker_connection::name_lookup(asio::error_code const& error , tcp::resolver::iterator i) try { @@ -759,7 +772,6 @@ namespace libtorrent if (m_parser.status_code() != 200) { fail(m_parser.status_code(), m_parser.message().c_str()); - close(); return; } @@ -821,6 +833,7 @@ namespace libtorrent TORRENT_ASSERT(false); } #endif + close(); } peer_entry http_tracker_connection::extract_peer_info(const entry& info) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 299ba96a7..68b252663 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -547,8 +547,8 @@ namespace detail , fingerprint const& cl_fprint , char const* listen_interface) : m_send_buffers(send_buffer_size) - , m_strand(m_io_service) , m_files(40) + , m_strand(m_io_service) , m_half_open(m_io_service) , m_download_channel(m_io_service, peer_connection::download_channel) , m_upload_channel(m_io_service, peer_connection::upload_channel) @@ -675,6 +675,14 @@ namespace detail if (m_dht) m_dht->stop(); #endif m_timer.cancel(); + + // close the listen sockets + for (std::list::iterator i = m_listen_sockets.begin() + , end(m_listen_sockets.end()); i != end; ++i) + { + i->sock->close(); + } + // abort all torrents for (torrent_map::iterator i = m_torrents.begin() , end(m_torrents.end()); i != end; ++i) @@ -682,7 +690,15 @@ namespace detail i->second->abort(); } - m_io_service.stop(); +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << time_now_string() << " aborting all tracker requests\n"; +#endif + m_tracker_manager.abort_all_requests(); + +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << time_now_string() << " shutting down connection queue\n"; +#endif + m_half_open.close(); mutex::scoped_lock l2(m_checker_impl.m_mutex); // abort the checker thread @@ -1474,20 +1490,12 @@ namespace detail while (!m_abort); deadline_timer tracker_timer(m_io_service); - // this will remove the port mappings - if (m_natpmp.get()) - m_natpmp->close(); - if (m_upnp.get()) - m_upnp->close(); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " locking mutex\n"; #endif session_impl::mutex_t::scoped_lock l(m_mutex); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all tracker requests\n"; -#endif m_tracker_manager.abort_all_requests(); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n"; @@ -2127,16 +2135,10 @@ namespace detail session_impl::~session_impl() { - abort(); - #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n"; #endif - // lock the main thread and abort it - mutex_t::scoped_lock l(m_mutex); - m_abort = true; - m_io_service.stop(); - l.unlock(); + abort(); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " waiting for main thread\n"; diff --git a/src/torrent.cpp b/src/torrent.cpp index 719f56853..6f764ed64 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -3055,7 +3055,7 @@ namespace libtorrent #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) void torrent::debug_log(const std::string& line) { - (*m_ses.m_logger) << line << "\n"; + (*m_ses.m_logger) << time_now_string() << " " << line << "\n"; } #endif diff --git a/src/tracker_manager.cpp b/src/tracker_manager.cpp index 0118e5802..eb10d5d94 100755 --- a/src/tracker_manager.cpp +++ b/src/tracker_manager.cpp @@ -302,12 +302,12 @@ namespace libtorrent { m_completion_timeout = completion_timeout; m_read_timeout = read_timeout; - m_start_time = time_now(); - m_read_time = time_now(); + m_start_time = m_read_time = time_now(); m_timeout.expires_at((std::min)( m_read_time + seconds(m_read_timeout) - , m_start_time + seconds(m_completion_timeout))); + , m_start_time + seconds((std::min)(m_completion_timeout + , m_read_timeout)))); m_timeout.async_wait(m_strand.wrap(bind( &timeout_handler::timeout_callback, self(), _1))); } @@ -343,7 +343,8 @@ namespace libtorrent m_timeout.expires_at((std::min)( m_read_time + seconds(m_read_timeout) - , m_start_time + seconds(m_completion_timeout))); + , m_start_time + seconds((std::min)(m_completion_timeout + , m_read_timeout)))); m_timeout.async_wait(m_strand.wrap( bind(&timeout_handler::timeout_callback, self(), _1))); } @@ -570,9 +571,12 @@ namespace libtorrent for (tracker_connections_t::const_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { + if (!*i) continue; tracker_request const& req = (*i)->tracker_req(); if (req.event == tracker_request::stopped) keep_connections.push_back(*i); + else + (*i)->close(); } std::swap(m_connections, keep_connections); diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index dd2ff10a1..6d76988d3 100755 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -96,7 +96,9 @@ namespace libtorrent m_name_lookup.async_resolve(q , m_strand.wrap(boost::bind( &udp_tracker_connection::name_lookup, self(), _1, _2))); - set_timeout(m_settings.tracker_completion_timeout + set_timeout(req.event == tracker_request::stopped + ? m_settings.stop_tracker_timeout + : m_settings.tracker_completion_timeout , m_settings.tracker_receive_timeout); } @@ -156,11 +158,20 @@ namespace libtorrent void udp_tracker_connection::on_timeout() { - m_socket.close(); + asio::error_code ec; + m_socket.close(ec); m_name_lookup.cancel(); fail_timeout(); } + void udp_tracker_connection::close() + { + asio::error_code ec; + m_socket.close(ec); + m_name_lookup.cancel(); + tracker_connection::close(); + } + void udp_tracker_connection::send_udp_connect() { #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) @@ -468,6 +479,7 @@ namespace libtorrent , complete, incomplete); m_man.remove_request(this); + close(); return; } catch (std::exception& e) @@ -543,6 +555,7 @@ namespace libtorrent if (!cb) { m_man.remove_request(this); + close(); return; } @@ -551,6 +564,7 @@ namespace libtorrent , complete, incomplete); m_man.remove_request(this); + close(); } catch (std::exception& e) {