forked from premiere/premiere-libtorrent
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
This commit is contained in:
parent
fe5e88b548
commit
8f07edbed2
|
@ -375,12 +375,6 @@ namespace libtorrent
|
||||||
// buffers from.
|
// buffers from.
|
||||||
boost::pool<> m_send_buffers;
|
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
|
// the file pool that all storages in this session's
|
||||||
// torrents uses. It sets a limit on the number of
|
// torrents uses. It sets a limit on the number of
|
||||||
// open files by this session.
|
// open files by this session.
|
||||||
|
@ -395,6 +389,12 @@ namespace libtorrent
|
||||||
// object.
|
// object.
|
||||||
disk_io_thread m_disk_thread;
|
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
|
// this is a list of half-open tcp connections
|
||||||
// (only outgoing connections)
|
// (only outgoing connections)
|
||||||
// this has to be one of the last
|
// this has to be one of the last
|
||||||
|
@ -646,7 +646,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void debug_log(const std::string& line)
|
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;
|
session_impl& m_ses;
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void done(int ticket);
|
void done(int ticket);
|
||||||
void limit(int limit);
|
void limit(int limit);
|
||||||
int limit() const;
|
int limit() const;
|
||||||
|
void close();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,8 @@ namespace libtorrent
|
||||||
, proxy_settings const& ps
|
, proxy_settings const& ps
|
||||||
, std::string const& password = "");
|
, std::string const& password = "");
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::intrusive_ptr<http_tracker_connection> self()
|
boost::intrusive_ptr<http_tracker_connection> self()
|
||||||
|
|
|
@ -202,7 +202,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void fail(int code, char const* msg);
|
void fail(int code, char const* msg);
|
||||||
void fail_timeout();
|
void fail_timeout();
|
||||||
void close();
|
virtual void close();
|
||||||
address const& bind_interface() const { return m_bind_interface; }
|
address const& bind_interface() const { return m_bind_interface; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -74,6 +74,8 @@ namespace libtorrent
|
||||||
, boost::weak_ptr<request_callback> c
|
, boost::weak_ptr<request_callback> c
|
||||||
, session_settings const& stn);
|
, session_settings const& stn);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum action_t
|
enum action_t
|
||||||
|
|
|
@ -86,6 +86,11 @@ namespace libtorrent
|
||||||
try_connect();
|
try_connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void connection_queue::close()
|
||||||
|
{
|
||||||
|
m_timer.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
void connection_queue::limit(int limit)
|
void connection_queue::limit(int limit)
|
||||||
{ m_half_open_limit = limit; }
|
{ m_half_open_limit = limit; }
|
||||||
|
|
||||||
|
|
|
@ -489,7 +489,9 @@ namespace libtorrent
|
||||||
, boost::lexical_cast<std::string>(m_port));
|
, boost::lexical_cast<std::string>(m_port));
|
||||||
m_name_lookup.async_resolve(q, m_strand.wrap(
|
m_name_lookup.async_resolve(q, m_strand.wrap(
|
||||||
boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2)));
|
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);
|
, m_settings.tracker_receive_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +505,17 @@ namespace libtorrent
|
||||||
fail_timeout();
|
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
|
void http_tracker_connection::name_lookup(asio::error_code const& error
|
||||||
, tcp::resolver::iterator i) try
|
, tcp::resolver::iterator i) try
|
||||||
{
|
{
|
||||||
|
@ -759,7 +772,6 @@ namespace libtorrent
|
||||||
if (m_parser.status_code() != 200)
|
if (m_parser.status_code() != 200)
|
||||||
{
|
{
|
||||||
fail(m_parser.status_code(), m_parser.message().c_str());
|
fail(m_parser.status_code(), m_parser.message().c_str());
|
||||||
close();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,6 +833,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(false);
|
TORRENT_ASSERT(false);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_entry http_tracker_connection::extract_peer_info(const entry& info)
|
peer_entry http_tracker_connection::extract_peer_info(const entry& info)
|
||||||
|
|
|
@ -547,8 +547,8 @@ namespace detail
|
||||||
, fingerprint const& cl_fprint
|
, fingerprint const& cl_fprint
|
||||||
, char const* listen_interface)
|
, char const* listen_interface)
|
||||||
: m_send_buffers(send_buffer_size)
|
: m_send_buffers(send_buffer_size)
|
||||||
, m_strand(m_io_service)
|
|
||||||
, m_files(40)
|
, m_files(40)
|
||||||
|
, m_strand(m_io_service)
|
||||||
, m_half_open(m_io_service)
|
, m_half_open(m_io_service)
|
||||||
, m_download_channel(m_io_service, peer_connection::download_channel)
|
, m_download_channel(m_io_service, peer_connection::download_channel)
|
||||||
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
, m_upload_channel(m_io_service, peer_connection::upload_channel)
|
||||||
|
@ -675,6 +675,14 @@ namespace detail
|
||||||
if (m_dht) m_dht->stop();
|
if (m_dht) m_dht->stop();
|
||||||
#endif
|
#endif
|
||||||
m_timer.cancel();
|
m_timer.cancel();
|
||||||
|
|
||||||
|
// close the listen sockets
|
||||||
|
for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
|
||||||
|
, end(m_listen_sockets.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
i->sock->close();
|
||||||
|
}
|
||||||
|
|
||||||
// abort all torrents
|
// abort all torrents
|
||||||
for (torrent_map::iterator i = m_torrents.begin()
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
, end(m_torrents.end()); i != end; ++i)
|
, end(m_torrents.end()); i != end; ++i)
|
||||||
|
@ -682,7 +690,15 @@ namespace detail
|
||||||
i->second->abort();
|
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);
|
mutex::scoped_lock l2(m_checker_impl.m_mutex);
|
||||||
// abort the checker thread
|
// abort the checker thread
|
||||||
|
@ -1474,20 +1490,12 @@ namespace detail
|
||||||
while (!m_abort);
|
while (!m_abort);
|
||||||
|
|
||||||
deadline_timer tracker_timer(m_io_service);
|
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)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " locking mutex\n";
|
(*m_logger) << time_now_string() << " locking mutex\n";
|
||||||
#endif
|
#endif
|
||||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
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();
|
m_tracker_manager.abort_all_requests();
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n";
|
(*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n";
|
||||||
|
@ -2127,16 +2135,10 @@ namespace detail
|
||||||
|
|
||||||
session_impl::~session_impl()
|
session_impl::~session_impl()
|
||||||
{
|
{
|
||||||
abort();
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
|
||||||
#endif
|
#endif
|
||||||
// lock the main thread and abort it
|
abort();
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
|
||||||
m_abort = true;
|
|
||||||
m_io_service.stop();
|
|
||||||
l.unlock();
|
|
||||||
|
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
(*m_logger) << time_now_string() << " waiting for main thread\n";
|
(*m_logger) << time_now_string() << " waiting for main thread\n";
|
||||||
|
|
|
@ -3055,7 +3055,7 @@ namespace libtorrent
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
void torrent::debug_log(const std::string& line)
|
void torrent::debug_log(const std::string& line)
|
||||||
{
|
{
|
||||||
(*m_ses.m_logger) << line << "\n";
|
(*m_ses.m_logger) << time_now_string() << " " << line << "\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -302,12 +302,12 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_completion_timeout = completion_timeout;
|
m_completion_timeout = completion_timeout;
|
||||||
m_read_timeout = read_timeout;
|
m_read_timeout = read_timeout;
|
||||||
m_start_time = time_now();
|
m_start_time = m_read_time = time_now();
|
||||||
m_read_time = time_now();
|
|
||||||
|
|
||||||
m_timeout.expires_at((std::min)(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
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(
|
m_timeout.async_wait(m_strand.wrap(bind(
|
||||||
&timeout_handler::timeout_callback, self(), _1)));
|
&timeout_handler::timeout_callback, self(), _1)));
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,8 @@ namespace libtorrent
|
||||||
|
|
||||||
m_timeout.expires_at((std::min)(
|
m_timeout.expires_at((std::min)(
|
||||||
m_read_time + seconds(m_read_timeout)
|
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(
|
m_timeout.async_wait(m_strand.wrap(
|
||||||
bind(&timeout_handler::timeout_callback, self(), _1)));
|
bind(&timeout_handler::timeout_callback, self(), _1)));
|
||||||
}
|
}
|
||||||
|
@ -570,9 +571,12 @@ namespace libtorrent
|
||||||
for (tracker_connections_t::const_iterator i =
|
for (tracker_connections_t::const_iterator i =
|
||||||
m_connections.begin(); i != m_connections.end(); ++i)
|
m_connections.begin(); i != m_connections.end(); ++i)
|
||||||
{
|
{
|
||||||
|
if (!*i) continue;
|
||||||
tracker_request const& req = (*i)->tracker_req();
|
tracker_request const& req = (*i)->tracker_req();
|
||||||
if (req.event == tracker_request::stopped)
|
if (req.event == tracker_request::stopped)
|
||||||
keep_connections.push_back(*i);
|
keep_connections.push_back(*i);
|
||||||
|
else
|
||||||
|
(*i)->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::swap(m_connections, keep_connections);
|
std::swap(m_connections, keep_connections);
|
||||||
|
|
|
@ -96,7 +96,9 @@ namespace libtorrent
|
||||||
m_name_lookup.async_resolve(q
|
m_name_lookup.async_resolve(q
|
||||||
, m_strand.wrap(boost::bind(
|
, m_strand.wrap(boost::bind(
|
||||||
&udp_tracker_connection::name_lookup, self(), _1, _2)));
|
&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);
|
, m_settings.tracker_receive_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +158,20 @@ namespace libtorrent
|
||||||
|
|
||||||
void udp_tracker_connection::on_timeout()
|
void udp_tracker_connection::on_timeout()
|
||||||
{
|
{
|
||||||
m_socket.close();
|
asio::error_code ec;
|
||||||
|
m_socket.close(ec);
|
||||||
m_name_lookup.cancel();
|
m_name_lookup.cancel();
|
||||||
fail_timeout();
|
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()
|
void udp_tracker_connection::send_udp_connect()
|
||||||
{
|
{
|
||||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||||
|
@ -468,6 +479,7 @@ namespace libtorrent
|
||||||
, complete, incomplete);
|
, complete, incomplete);
|
||||||
|
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
@ -543,6 +555,7 @@ namespace libtorrent
|
||||||
if (!cb)
|
if (!cb)
|
||||||
{
|
{
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +564,7 @@ namespace libtorrent
|
||||||
, complete, incomplete);
|
, complete, incomplete);
|
||||||
|
|
||||||
m_man.remove_request(this);
|
m_man.remove_request(this);
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue