shutdown improvements. Fixes stall
This commit is contained in:
parent
c982ba5d90
commit
fd51412b70
|
@ -184,6 +184,7 @@ namespace libtorrent
|
|||
|
||||
typedef boost::mutex mutex_t;
|
||||
mutable mutex_t m_mutex;
|
||||
bool m_abort;
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT tracker_connection
|
||||
|
|
|
@ -116,8 +116,14 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (!free_slots() || m_queue.empty())
|
||||
if (!free_slots())
|
||||
return;
|
||||
|
||||
if (m_queue.empty())
|
||||
{
|
||||
m_timer.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<entry>::iterator i = std::find_if(m_queue.begin()
|
||||
, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
|
||||
|
|
|
@ -514,6 +514,12 @@ namespace libtorrent
|
|||
m_connection_ticket = -1;
|
||||
m_timed_out = true;
|
||||
tracker_connection::close();
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
std::stringstream msg;
|
||||
msg << "http_tracker_connection::close() " << m_man.num_requests();
|
||||
if (cb) cb->debug_log(msg.str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void http_tracker_connection::name_lookup(asio::error_code const& error
|
||||
|
|
|
@ -693,21 +693,61 @@ namespace detail
|
|||
i->second->abort();
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " aborting all connections\n";
|
||||
#endif
|
||||
// abort all connections
|
||||
for (connection_map::iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
{
|
||||
(*i)->disconnect();
|
||||
}
|
||||
|
||||
#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 event=stopped to trackers\n";
|
||||
int counter = 0;
|
||||
#endif
|
||||
for (torrent_map::iterator i = m_torrents.begin();
|
||||
i != m_torrents.end(); ++i)
|
||||
{
|
||||
torrent& t = *i->second;
|
||||
|
||||
if ((!t.is_paused() || t.should_request())
|
||||
&& !t.trackers().empty())
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
++counter;
|
||||
#endif
|
||||
tracker_request req = t.generate_tracker_request();
|
||||
TORRENT_ASSERT(req.event == tracker_request::stopped);
|
||||
req.listen_port = 0;
|
||||
if (!m_listen_sockets.empty())
|
||||
req.listen_port = m_listen_sockets.front().external_port;
|
||||
req.key = m_key;
|
||||
std::string login = i->second->tracker_login();
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
boost::shared_ptr<tracker_logger> tl(new tracker_logger(*this));
|
||||
m_tracker_loggers.push_back(tl);
|
||||
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
|
||||
, m_listen_interface.address(), tl);
|
||||
#else
|
||||
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
|
||||
, m_listen_interface.address());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n";
|
||||
#endif
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n";
|
||||
#endif
|
||||
// abort all connections
|
||||
while (!m_connections.empty())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
int conn = m_connections.size();
|
||||
#endif
|
||||
(*m_connections.begin())->disconnect();
|
||||
TORRENT_ASSERT(conn == m_connections.size() + 1);
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " shutting down connection queue\n";
|
||||
#endif
|
||||
|
@ -1513,88 +1553,11 @@ namespace detail
|
|||
}
|
||||
while (!m_abort);
|
||||
|
||||
deadline_timer tracker_timer(m_io_service);
|
||||
|
||||
#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);
|
||||
|
||||
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";
|
||||
#endif
|
||||
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i =
|
||||
m_torrents.begin(); i != m_torrents.end(); ++i)
|
||||
{
|
||||
i->second->abort();
|
||||
// generate a tracker request in case the torrent is not paused
|
||||
// (in which case it's not currently announced with the tracker)
|
||||
// or if the torrent itself thinks we should request. Do not build
|
||||
// a request in case the torrent doesn't have any trackers
|
||||
if ((!i->second->is_paused() || i->second->should_request())
|
||||
&& !i->second->trackers().empty())
|
||||
{
|
||||
tracker_request req = i->second->generate_tracker_request();
|
||||
TORRENT_ASSERT(!m_listen_sockets.empty());
|
||||
req.listen_port = 0;
|
||||
if (!m_listen_sockets.empty())
|
||||
req.listen_port = m_listen_sockets.front().external_port;
|
||||
req.key = m_key;
|
||||
std::string login = i->second->tracker_login();
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
boost::shared_ptr<tracker_logger> tl(new tracker_logger(*this));
|
||||
m_tracker_loggers.push_back(tl);
|
||||
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
|
||||
, m_listen_interface.address(), tl);
|
||||
#else
|
||||
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
|
||||
, m_listen_interface.address());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// close the listen sockets
|
||||
m_listen_sockets.clear();
|
||||
|
||||
ptime start(time_now());
|
||||
l.unlock();
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " waiting for trackers to respond ("
|
||||
<< m_settings.stop_tracker_timeout << " seconds timeout)\n";
|
||||
#endif
|
||||
|
||||
while (time_now() - start < seconds(
|
||||
m_settings.stop_tracker_timeout)
|
||||
&& !m_tracker_manager.empty())
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " " << m_tracker_manager.num_requests()
|
||||
<< " tracker requests pending\n";
|
||||
#endif
|
||||
tracker_timer.expires_from_now(milliseconds(100));
|
||||
tracker_timer.async_wait(m_strand.wrap(
|
||||
bind(&io_service::stop, &m_io_service)));
|
||||
|
||||
m_io_service.reset();
|
||||
m_io_service.run();
|
||||
}
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " tracker shutdown complete, locking mutex\n";
|
||||
#endif
|
||||
|
||||
l.lock();
|
||||
TORRENT_ASSERT(m_abort);
|
||||
m_abort = true;
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << time_now_string() << " cleaning up connections\n";
|
||||
#endif
|
||||
while (!m_connections.empty())
|
||||
(*m_connections.begin())->disconnect();
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (torrent_map::iterator i = m_torrents.begin();
|
||||
i != m_torrents.end(); ++i)
|
||||
|
|
|
@ -296,6 +296,7 @@ namespace libtorrent
|
|||
, m_timeout(str.io_service())
|
||||
, m_completion_timeout(0)
|
||||
, m_read_timeout(0)
|
||||
, m_abort(false)
|
||||
{}
|
||||
|
||||
void timeout_handler::set_timeout(int completion_timeout, int read_timeout)
|
||||
|
@ -304,10 +305,11 @@ namespace libtorrent
|
|||
m_read_timeout = read_timeout;
|
||||
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((std::min)(m_completion_timeout
|
||||
, m_read_timeout))));
|
||||
if (m_abort) return;
|
||||
|
||||
int timeout = (std::min)(
|
||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
||||
m_timeout.expires_at(m_read_time + seconds(timeout));
|
||||
m_timeout.async_wait(m_strand.wrap(bind(
|
||||
&timeout_handler::timeout_callback, self(), _1)));
|
||||
}
|
||||
|
@ -319,6 +321,7 @@ namespace libtorrent
|
|||
|
||||
void timeout_handler::cancel()
|
||||
{
|
||||
m_abort = true;
|
||||
m_completion_timeout = 0;
|
||||
m_timeout.cancel();
|
||||
}
|
||||
|
@ -341,10 +344,11 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
m_timeout.expires_at((std::min)(
|
||||
m_read_time + seconds(m_read_timeout)
|
||||
, m_start_time + seconds((std::min)(m_completion_timeout
|
||||
, m_read_timeout))));
|
||||
if (m_abort) return;
|
||||
|
||||
int timeout = (std::min)(
|
||||
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
|
||||
m_timeout.expires_at(m_read_time + seconds(timeout));
|
||||
m_timeout.async_wait(m_strand.wrap(
|
||||
bind(&timeout_handler::timeout_callback, self(), _1)));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue