forked from premiere/premiere-libtorrent
handle exceptions in session and torrent io_service jobs (#1185)
handle exceptions in session and torrent io_service jobs
This commit is contained in:
parent
3c355bb3f8
commit
5c361715da
|
@ -2396,11 +2396,32 @@ namespace libtorrent
|
|||
int const m_num_blocks;
|
||||
};
|
||||
|
||||
// this alert is posted when the session encounters a serious error,
|
||||
// potentially fatal
|
||||
struct TORRENT_EXPORT session_error_alert : alert
|
||||
{
|
||||
// internal
|
||||
session_error_alert(aux::stack_allocator& alloc, error_code err
|
||||
, string_view error_str);
|
||||
|
||||
TORRENT_DEFINE_ALERT(session_error_alert, 90)
|
||||
|
||||
static const int static_category = alert::error_notification;
|
||||
std::string message() const override;
|
||||
|
||||
// The error code, if one is associated with this error
|
||||
error_code error;
|
||||
|
||||
private:
|
||||
std::reference_wrapper<aux::stack_allocator> m_alloc;
|
||||
int const m_msg_idx;
|
||||
};
|
||||
|
||||
#undef TORRENT_DEFINE_ALERT_IMPL
|
||||
#undef TORRENT_DEFINE_ALERT
|
||||
#undef TORRENT_DEFINE_ALERT_PRIO
|
||||
|
||||
enum { num_alert_types = 90 }; // this enum represents "max_alert_index" + 1
|
||||
enum { num_alert_types = 91 }; // this enum represents "max_alert_index" + 1
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -207,6 +207,9 @@ namespace libtorrent
|
|||
plugins_dht_request_idx = 3 // dht_request_feature
|
||||
};
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void wrap(Fun f, Args&&... a);
|
||||
|
||||
#if TORRENT_USE_INVARIANT_CHECKS
|
||||
friend class libtorrent::invariant_access;
|
||||
#endif
|
||||
|
|
|
@ -971,6 +971,9 @@ namespace libtorrent
|
|||
int time_since_complete() const { return int(time(0) - m_last_seen_complete); }
|
||||
time_t last_seen_complete() const { return m_last_seen_complete; }
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void wrap(Fun f, Args&&... a);
|
||||
|
||||
// LOGGING
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
virtual bool should_log() const override;
|
||||
|
@ -1139,10 +1142,7 @@ namespace libtorrent
|
|||
|
||||
void update_tracker_timer(time_point now);
|
||||
|
||||
static void on_tracker_announce_disp(std::weak_ptr<torrent> p
|
||||
, error_code const& e);
|
||||
|
||||
void on_tracker_announce();
|
||||
void on_tracker_announce(error_code const& ec);
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
static void on_dht_announce_response_disp(std::weak_ptr<torrent> t
|
||||
|
@ -1433,10 +1433,10 @@ namespace libtorrent
|
|||
// is is disabled while paused and checking files
|
||||
bool m_announcing:1;
|
||||
|
||||
// this is true while the tracker deadline timer
|
||||
// this is > 0 while the tracker deadline timer
|
||||
// is in use. i.e. one or more trackers are waiting
|
||||
// for a reannounce
|
||||
bool m_waiting_tracker:1;
|
||||
std::int8_t m_waiting_tracker = 0;
|
||||
|
||||
// ----
|
||||
|
||||
|
@ -1503,7 +1503,7 @@ namespace libtorrent
|
|||
|
||||
// these are the flags sent in on a call to save_resume_data
|
||||
// we need to save them to check them in write_resume_data
|
||||
std::uint8_t m_save_resume_flags;
|
||||
std::uint8_t m_save_resume_flags = 0;
|
||||
|
||||
// ----
|
||||
|
||||
|
|
|
@ -140,7 +140,11 @@ namespace libtorrent
|
|||
|
||||
// the error occurred while loading the .torrent file via the user
|
||||
// supplied load function
|
||||
error_file_metadata = -4
|
||||
error_file_metadata = -4,
|
||||
|
||||
// there was a serious error reported in this torrent. The error code
|
||||
// or a torrent log alert may provide more information.
|
||||
error_file_exception = -5,
|
||||
};
|
||||
|
||||
// the path to the directory where this torrent's files are stored.
|
||||
|
|
|
@ -1261,8 +1261,17 @@ namespace libtorrent {
|
|||
|
||||
std::string torrent_error_alert::message() const
|
||||
{
|
||||
char msg[200];
|
||||
std::snprintf(msg, sizeof(msg), " ERROR: %s", convert_from_native(error.message()).c_str());
|
||||
char msg[400];
|
||||
if (error)
|
||||
{
|
||||
std::snprintf(msg, sizeof(msg), " ERROR: (%d %s) %s"
|
||||
, error.value(), convert_from_native(error.message()).c_str()
|
||||
, filename());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::snprintf(msg, sizeof(msg), " ERROR: %s", filename());
|
||||
}
|
||||
return torrent_alert::message() + msg;
|
||||
}
|
||||
|
||||
|
@ -1689,7 +1698,7 @@ namespace libtorrent {
|
|||
|
||||
std::string lsd_error_alert::message() const
|
||||
{
|
||||
return "Local Service Discovery error: " + error.message();
|
||||
return "Local Service Discovery error: " + convert_from_native(error.message());
|
||||
}
|
||||
|
||||
session_stats_alert::session_stats_alert(aux::stack_allocator&, counters const& cnt)
|
||||
|
@ -2049,4 +2058,29 @@ namespace libtorrent {
|
|||
return ret;
|
||||
}
|
||||
|
||||
session_error_alert::session_error_alert(aux::stack_allocator& alloc
|
||||
, error_code e, string_view error_str)
|
||||
: error(e)
|
||||
, m_alloc(alloc)
|
||||
, m_msg_idx(alloc.copy_buffer(error_str))
|
||||
{}
|
||||
|
||||
std::string session_error_alert::message() const
|
||||
{
|
||||
char buf[400];
|
||||
if (error)
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "session error: (%d %s) %s"
|
||||
, error.value(), convert_from_native(error.message()).c_str()
|
||||
, m_alloc.get().ptr(m_msg_idx));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::snprintf(buf, sizeof(buf), "session error: %s"
|
||||
, m_alloc.get().ptr(m_msg_idx));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // namespace libtorrent
|
||||
|
||||
|
|
|
@ -3509,7 +3509,7 @@ namespace libtorrent
|
|||
|
||||
std::unique_lock<std::mutex> l(m_completed_jobs_mutex);
|
||||
|
||||
bool need_post = m_completed_jobs.size() == 0;
|
||||
bool const need_post = m_completed_jobs.size() == 0;
|
||||
m_completed_jobs.append(jobs);
|
||||
l.unlock();
|
||||
|
||||
|
@ -3524,6 +3524,9 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
// This is run in the network thread
|
||||
// TODO: 2 it would be nice to get rid of m_userdata and just have a function
|
||||
// object to pass all the job completions to. It could in turn be responsible
|
||||
// for posting them to the correct io_servive
|
||||
void disk_io_thread::call_job_handlers(void* userdata)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(m_completed_jobs_mutex);
|
||||
|
@ -3532,7 +3535,7 @@ namespace libtorrent
|
|||
DLOG("call_job_handlers (%d)\n", m_completed_jobs.size());
|
||||
#endif
|
||||
|
||||
int num_jobs = m_completed_jobs.size();
|
||||
int const num_jobs = m_completed_jobs.size();
|
||||
disk_io_job* j = m_completed_jobs.get_all();
|
||||
l.unlock();
|
||||
|
||||
|
|
|
@ -49,7 +49,21 @@ namespace libtorrent
|
|||
void session_handle::async_call(Fun f, Args&&... a) const
|
||||
{
|
||||
m_impl->get_io_service().dispatch([=]() mutable
|
||||
{ (m_impl->*f)(a...); });
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(m_impl->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (system_error const& e) {
|
||||
m_impl->alerts().emplace_alert<session_error_alert>(e.code(), e.what());
|
||||
} catch (std::exception const& e) {
|
||||
m_impl->alerts().emplace_alert<session_error_alert>(error_code(), e.what());
|
||||
} catch (...) {
|
||||
m_impl->alerts().emplace_alert<session_error_alert>(error_code(), "unknown error");
|
||||
}
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Fun, typename... Args>
|
||||
|
@ -60,15 +74,25 @@ namespace libtorrent
|
|||
// and simplify the capture expression
|
||||
bool done = false;
|
||||
|
||||
m_impl->get_io_service().dispatch([=,&done]() mutable
|
||||
std::exception_ptr ex;
|
||||
m_impl->get_io_service().dispatch([=,&done,&ex]() mutable
|
||||
{
|
||||
(m_impl->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(m_impl->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
#endif
|
||||
std::unique_lock<std::mutex> l(m_impl->mut);
|
||||
done = true;
|
||||
m_impl->cond.notify_all();
|
||||
});
|
||||
|
||||
aux::torrent_wait(done, *m_impl);
|
||||
if (ex) std::rethrow_exception(ex);
|
||||
}
|
||||
|
||||
template<typename Ret, typename Fun, typename... Args>
|
||||
|
@ -79,15 +103,25 @@ namespace libtorrent
|
|||
// and simplify the capture expression
|
||||
bool done = false;
|
||||
Ret r;
|
||||
m_impl->get_io_service().dispatch([=,&r,&done]() mutable
|
||||
std::exception_ptr ex;
|
||||
m_impl->get_io_service().dispatch([=,&r,&done,&ex]() mutable
|
||||
{
|
||||
r = (m_impl->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
r = (m_impl->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
#endif
|
||||
std::unique_lock<std::mutex> l(m_impl->mut);
|
||||
done = true;
|
||||
m_impl->cond.notify_all();
|
||||
});
|
||||
|
||||
aux::torrent_wait(done, *m_impl);
|
||||
if (ex) std::rethrow_exception(ex);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -195,6 +195,7 @@ namespace libtorrent {
|
|||
|
||||
namespace aux {
|
||||
|
||||
// TODO: 3 move this out of this file
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
dht_settings read_dht_settings(bdecode_node const& e)
|
||||
{
|
||||
|
@ -443,6 +444,27 @@ namespace aux {
|
|||
update_time_now();
|
||||
}
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void session_impl::wrap(Fun f, Args&&... a)
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
(this->*f)(std::forward<Args>(a)...);
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (system_error const& e) {
|
||||
alerts().emplace_alert<session_error_alert>(e.code(), e.what());
|
||||
pause();
|
||||
} catch (std::exception const& e) {
|
||||
alerts().emplace_alert<session_error_alert>(error_code(), e.what());
|
||||
pause();
|
||||
} catch (...) {
|
||||
alerts().emplace_alert<session_error_alert>(error_code(), "unknown error");
|
||||
pause();
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function is called by the creating thread, not in the message loop's
|
||||
// io_service thread.
|
||||
// TODO: 2 is there a reason not to move all of this into init()? and just
|
||||
|
@ -520,8 +542,10 @@ namespace aux {
|
|||
}
|
||||
#endif
|
||||
|
||||
// TODO: 3 make this move all the way through to the init() call
|
||||
// if we're in C++14
|
||||
auto copy = std::make_shared<settings_pack>(std::move(pack));
|
||||
m_io_service.post(std::bind(&session_impl::init, this, copy));
|
||||
m_io_service.post([this, copy] { this->wrap(&session_impl::init, copy); });
|
||||
}
|
||||
|
||||
void session_impl::init(std::shared_ptr<settings_pack> pack)
|
||||
|
@ -566,15 +590,15 @@ namespace aux {
|
|||
async_inc_threads();
|
||||
add_outstanding_async("session_impl::on_tick");
|
||||
#endif
|
||||
error_code ec;
|
||||
m_io_service.post(std::bind(&session_impl::on_tick, this, ec));
|
||||
m_io_service.post([this]{ this->wrap(&session_impl::on_tick, error_code()); });
|
||||
|
||||
error_code ec;
|
||||
ADD_OUTSTANDING_ASYNC("session_impl::on_lsd_announce");
|
||||
int delay = (std::max)(m_settings.get_int(settings_pack::local_service_announce_interval)
|
||||
/ (std::max)(int(m_torrents.size()), 1), 1);
|
||||
int const delay = std::max(m_settings.get_int(settings_pack::local_service_announce_interval)
|
||||
/ std::max(int(m_torrents.size()), 1), 1);
|
||||
m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
|
||||
m_lsd_announce_timer.async_wait(
|
||||
std::bind(&session_impl::on_lsd_announce, this, _1));
|
||||
m_lsd_announce_timer.async_wait([this](error_code const& e) {
|
||||
this->wrap(&session_impl::on_lsd_announce, e); } );
|
||||
TORRENT_ASSERT(!ec);
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
@ -1339,7 +1363,7 @@ namespace aux {
|
|||
{
|
||||
if (m_deferred_submit_disk_jobs) return;
|
||||
m_deferred_submit_disk_jobs = true;
|
||||
m_io_service.post(std::bind(&session_impl::submit_disk_jobs, this));
|
||||
m_io_service.post([this] { this->wrap(&session_impl::submit_disk_jobs); } );
|
||||
}
|
||||
|
||||
void session_impl::submit_disk_jobs()
|
||||
|
@ -3136,7 +3160,8 @@ namespace aux {
|
|||
ADD_OUTSTANDING_ASYNC("session_impl::on_tick");
|
||||
error_code ec;
|
||||
m_timer.expires_at(now + milliseconds(m_settings.get_int(settings_pack::tick_interval)), ec);
|
||||
m_timer.async_wait(make_tick_handler(std::bind(&session_impl::on_tick, this, _1)));
|
||||
m_timer.async_wait(make_tick_handler([this](error_code const& err) {
|
||||
this->wrap(&session_impl::on_tick, err); }));
|
||||
|
||||
m_download_rate.update_quotas(now - m_last_tick);
|
||||
m_upload_rate.update_quotas(now - m_last_tick);
|
||||
|
@ -3525,8 +3550,8 @@ namespace aux {
|
|||
ADD_OUTSTANDING_ASYNC("session_impl::on_dht_announce");
|
||||
error_code ec;
|
||||
m_dht_announce_timer.expires_from_now(seconds(0), ec);
|
||||
m_dht_announce_timer.async_wait(
|
||||
std::bind(&session_impl::on_dht_announce, this, _1));
|
||||
m_dht_announce_timer.async_wait([this](error_code const& err) {
|
||||
this->wrap(&session_impl::on_dht_announce, err); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3577,8 +3602,9 @@ namespace aux {
|
|||
ADD_OUTSTANDING_ASYNC("session_impl::on_dht_announce");
|
||||
error_code ec;
|
||||
m_dht_announce_timer.expires_from_now(seconds(delay), ec);
|
||||
m_dht_announce_timer.async_wait(
|
||||
std::bind(&session_impl::on_dht_announce, this, _1));
|
||||
m_dht_announce_timer.async_wait([this](error_code const& err) {
|
||||
this->wrap(&session_impl::on_dht_announce, err); }
|
||||
);
|
||||
|
||||
if (!m_dht_torrents.empty())
|
||||
{
|
||||
|
@ -3623,8 +3649,8 @@ namespace aux {
|
|||
/ (std::max)(int(m_torrents.size()), 1), 1);
|
||||
error_code ec;
|
||||
m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
|
||||
m_lsd_announce_timer.async_wait(
|
||||
std::bind(&session_impl::on_lsd_announce, this, _1));
|
||||
m_lsd_announce_timer.async_wait([this](error_code const& err) {
|
||||
this->wrap(&session_impl::on_lsd_announce, err); });
|
||||
|
||||
if (m_torrents.empty()) return;
|
||||
|
||||
|
@ -4358,6 +4384,8 @@ namespace aux {
|
|||
|
||||
void session_impl::set_queue_position(torrent* me, int p)
|
||||
{
|
||||
// TODO: Maybe the queue position should be maintained as a vector of
|
||||
// torrent pointers. Maybe this logic could be simplified
|
||||
if (p >= 0 && me->queue_position() == -1)
|
||||
{
|
||||
for (session_impl::torrent_map::iterator i = m_torrents.begin()
|
||||
|
@ -4531,29 +4559,26 @@ namespace aux {
|
|||
|
||||
void session_impl::get_torrent_status(std::vector<torrent_status>* ret
|
||||
, std::function<bool(torrent_status const&)> const& pred
|
||||
, std::uint32_t flags) const
|
||||
, std::uint32_t const flags) const
|
||||
{
|
||||
for (torrent_map::const_iterator i
|
||||
= m_torrents.begin(), end(m_torrents.end());
|
||||
i != end; ++i)
|
||||
for (auto const& t : m_torrents)
|
||||
{
|
||||
if (i->second->is_aborted()) continue;
|
||||
if (t.second->is_aborted()) continue;
|
||||
torrent_status st;
|
||||
i->second->status(&st, flags);
|
||||
t.second->status(&st, flags);
|
||||
if (!pred(st)) continue;
|
||||
ret->push_back(st);
|
||||
ret->push_back(std::move(st));
|
||||
}
|
||||
}
|
||||
|
||||
void session_impl::refresh_torrent_status(std::vector<torrent_status>* ret
|
||||
, std::uint32_t flags) const
|
||||
, std::uint32_t const flags) const
|
||||
{
|
||||
for (std::vector<torrent_status>::iterator i
|
||||
= ret->begin(), end(ret->end()); i != end; ++i)
|
||||
for (auto& st : *ret)
|
||||
{
|
||||
std::shared_ptr<torrent> t = i->handle.m_torrent.lock();
|
||||
auto t = st.handle.m_torrent.lock();
|
||||
if (!t) continue;
|
||||
t->status(&*i, flags);
|
||||
t->status(&st, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6183,7 +6208,7 @@ namespace aux {
|
|||
m_pending_auto_manage = true;
|
||||
m_need_auto_manage = true;
|
||||
|
||||
m_io_service.post(std::bind(&session_impl::on_trigger_auto_manage, this));
|
||||
m_io_service.post([this]{ this->wrap(&session_impl::on_trigger_auto_manage); });
|
||||
}
|
||||
|
||||
void session_impl::on_trigger_auto_manage()
|
||||
|
@ -6256,8 +6281,8 @@ namespace aux {
|
|||
int delay = (std::max)(m_settings.get_int(settings_pack::dht_announce_interval)
|
||||
/ (std::max)(int(m_torrents.size()), 1), 1);
|
||||
m_dht_announce_timer.expires_from_now(seconds(delay), ec);
|
||||
m_dht_announce_timer.async_wait(
|
||||
std::bind(&session_impl::on_dht_announce, this, _1));
|
||||
m_dht_announce_timer.async_wait([this](error_code const& e) {
|
||||
this->wrap(&session_impl::on_dht_announce, e); });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
122
src/torrent.cpp
122
src/torrent.cpp
|
@ -189,7 +189,6 @@ namespace libtorrent
|
|||
, m_files_checked(false)
|
||||
, m_storage_mode(p.storage_mode)
|
||||
, m_announcing(false)
|
||||
, m_waiting_tracker(false)
|
||||
, m_active_time(0)
|
||||
, m_finished_time(0)
|
||||
, m_sequential_download(false)
|
||||
|
@ -200,7 +199,6 @@ namespace libtorrent
|
|||
, m_need_save_resume_data((p.flags & add_torrent_params::flag_need_save_resume) != 0)
|
||||
, m_seeding_time(0)
|
||||
, m_max_uploads((1<<24)-1)
|
||||
, m_save_resume_flags(0)
|
||||
, m_num_uploads(0)
|
||||
, m_need_connect_boost(true)
|
||||
, m_lsd_seq(0)
|
||||
|
@ -424,7 +422,7 @@ namespace libtorrent
|
|||
// as we replace the torrent_info object
|
||||
// we're about to erase the session's reference to this
|
||||
// torrent, create another reference
|
||||
std::shared_ptr<torrent> me(shared_from_this());
|
||||
auto me = shared_from_this();
|
||||
|
||||
m_ses.remove_torrent_impl(me, 0);
|
||||
|
||||
|
@ -1804,7 +1802,8 @@ namespace libtorrent
|
|||
if (m_seed_mode)
|
||||
{
|
||||
m_have_all = true;
|
||||
m_ses.get_io_service().post(std::bind(&torrent::files_checked, shared_from_this()));
|
||||
auto self = shared_from_this();
|
||||
m_ses.get_io_service().post([self] { self->wrap(&torrent::files_checked); });
|
||||
TORRENT_ASSERT(m_outstanding_check_files == false);
|
||||
m_add_torrent_params.reset();
|
||||
update_gauge();
|
||||
|
@ -2667,21 +2666,13 @@ namespace libtorrent
|
|||
}
|
||||
#endif
|
||||
|
||||
void torrent::on_tracker_announce_disp(std::weak_ptr<torrent> p
|
||||
, error_code const& e)
|
||||
{
|
||||
COMPLETE_ASYNC("tracker::on_tracker_announce_disp");
|
||||
std::shared_ptr<torrent> t = p.lock();
|
||||
if (!t) return;
|
||||
t->m_waiting_tracker = false;
|
||||
|
||||
if (e) return;
|
||||
t->on_tracker_announce();
|
||||
}
|
||||
|
||||
void torrent::on_tracker_announce()
|
||||
void torrent::on_tracker_announce(error_code const& ec)
|
||||
{
|
||||
COMPLETE_ASYNC("tracker::on_tracker_announce");
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
TORRENT_ASSERT(m_waiting_tracker > 0);
|
||||
--m_waiting_tracker;
|
||||
if (ec) return;
|
||||
if (m_abort) return;
|
||||
announce_with_tracker();
|
||||
}
|
||||
|
@ -3501,7 +3492,7 @@ namespace libtorrent
|
|||
|
||||
time_point torrent::next_announce() const
|
||||
{
|
||||
return m_waiting_tracker?m_tracker_timer.expires_at():min_time();
|
||||
return m_waiting_tracker ? m_tracker_timer.expires_at() : min_time();
|
||||
}
|
||||
|
||||
// this is the entry point for the client to force a re-announce. It's
|
||||
|
@ -4065,9 +4056,7 @@ namespace libtorrent
|
|||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (auto& ext : m_extensions)
|
||||
{
|
||||
TORRENT_TRY {
|
||||
ext->on_piece_pass(index);
|
||||
} TORRENT_CATCH (std::exception const&) {}
|
||||
ext->on_piece_pass(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4270,9 +4259,7 @@ namespace libtorrent
|
|||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (auto& ext : m_extensions)
|
||||
{
|
||||
TORRENT_TRY {
|
||||
ext->on_piece_failed(index);
|
||||
} TORRENT_CATCH (std::exception const&) {}
|
||||
ext->on_piece_failed(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4743,6 +4730,42 @@ namespace libtorrent
|
|||
return detail::read_uint32(ptr);
|
||||
}
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void torrent::wrap(Fun f, Args&&... a)
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
(this->*f)(std::forward<Args>(a)...);
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (system_error const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: (%d %s) %s"
|
||||
, e.code().value()
|
||||
, e.code().message().c_str()
|
||||
, e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, e.code(), e.what());
|
||||
pause();
|
||||
} catch (std::exception const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: %s", e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), e.what());
|
||||
pause();
|
||||
} catch (...) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: unknown");
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), "unknown error");
|
||||
pause();
|
||||
}
|
||||
#endif
|
||||
|
||||
void torrent::cancel_non_critical()
|
||||
{
|
||||
std::set<int> time_critical;
|
||||
|
@ -4810,9 +4833,10 @@ namespace libtorrent
|
|||
if (m_time_critical_pieces.empty())
|
||||
{
|
||||
// defer this by posting it to the end of the message queue.
|
||||
// this gives the client a chance to specify multiple time critical
|
||||
// this gives the client a chance to specify multiple time-critical
|
||||
// pieces before libtorrent cancels requests
|
||||
m_ses.get_io_service().post(std::bind(&torrent::cancel_non_critical, this));
|
||||
auto self = shared_from_this();
|
||||
m_ses.get_io_service().post([self] { self->wrap(&torrent::cancel_non_critical); });
|
||||
}
|
||||
|
||||
for (std::vector<time_critical_piece>::iterator i = m_time_critical_pieces.begin()
|
||||
|
@ -5941,11 +5965,16 @@ namespace libtorrent
|
|||
debug_log("resolving proxy for web seed: %s", web->url.c_str());
|
||||
#endif
|
||||
|
||||
auto self = shared_from_this();
|
||||
std::uint16_t const proxy_port = ps.port;
|
||||
|
||||
// use proxy
|
||||
web->resolving = true;
|
||||
m_ses.async_resolve(ps.hostname, resolver_interface::abort_on_shutdown
|
||||
, std::bind(&torrent::on_proxy_name_lookup, shared_from_this()
|
||||
, _1, _2, web, ps.port));
|
||||
, [self,web,proxy_port](error_code const& e, std::vector<address> const& addrs)
|
||||
{
|
||||
self->wrap(&torrent::on_proxy_name_lookup, e, addrs, web, proxy_port);
|
||||
});
|
||||
}
|
||||
else if (ps.proxy_hostnames
|
||||
&& (ps.type == settings_pack::socks5
|
||||
|
@ -5960,10 +5989,14 @@ namespace libtorrent
|
|||
debug_log("resolving web seed: \"%s\" %s", hostname.c_str(), web->url.c_str());
|
||||
#endif
|
||||
|
||||
auto self = shared_from_this();
|
||||
web->resolving = true;
|
||||
|
||||
m_ses.async_resolve(hostname, resolver_interface::abort_on_shutdown
|
||||
, std::bind(&torrent::on_name_lookup, shared_from_this(), _1, _2
|
||||
, port, web));
|
||||
, [self,web,port](error_code const& e, std::vector<address> const& addrs)
|
||||
{
|
||||
self->wrap(&torrent::on_name_lookup, e, addrs, port, web);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6043,10 +6076,13 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
auto self = shared_from_this();
|
||||
web->resolving = true;
|
||||
m_ses.async_resolve(hostname, resolver_interface::abort_on_shutdown
|
||||
, std::bind(&torrent::on_name_lookup, shared_from_this(), _1, _2
|
||||
, port, web));
|
||||
, [self,web,port](error_code const& err, std::vector<address> const& addr)
|
||||
{
|
||||
self->wrap(&torrent::on_name_lookup, err, addr, port, web);
|
||||
});
|
||||
}
|
||||
|
||||
void torrent::on_name_lookup(error_code const& e
|
||||
|
@ -9209,16 +9245,17 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
// don't re-issue the timer if it's the same expiration time as last time
|
||||
// if m_waiting_tracker is false, expires_at() is undefined
|
||||
// if m_waiting_tracker is 0, expires_at() is undefined
|
||||
if (m_waiting_tracker && m_tracker_timer.expires_at() == next_announce) return;
|
||||
|
||||
m_waiting_tracker = true;
|
||||
error_code ec;
|
||||
std::weak_ptr<torrent> self(shared_from_this());
|
||||
auto self = shared_from_this();
|
||||
|
||||
ADD_OUTSTANDING_ASYNC("tracker::on_tracker_announce_disp");
|
||||
m_tracker_timer.expires_at(next_announce, ec);
|
||||
m_tracker_timer.async_wait(std::bind(&torrent::on_tracker_announce_disp, self, _1));
|
||||
ADD_OUTSTANDING_ASYNC("tracker::on_tracker_announce");
|
||||
++m_waiting_tracker;
|
||||
m_tracker_timer.async_wait([self](error_code const& e)
|
||||
{ self->wrap(&torrent::on_tracker_announce, e); });
|
||||
}
|
||||
|
||||
void torrent::start_announcing()
|
||||
|
@ -9337,7 +9374,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(is_single_thread());
|
||||
INVARIANT_CHECK;
|
||||
|
||||
std::weak_ptr<torrent> self(shared_from_this());
|
||||
auto self = shared_from_this();
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (auto const& ext : m_extensions)
|
||||
|
@ -9499,13 +9536,12 @@ namespace libtorrent
|
|||
|
||||
if (settings().get_bool(settings_pack::dont_count_slow_torrents))
|
||||
{
|
||||
if (is_inactive != m_inactive
|
||||
&& !m_pending_active_change)
|
||||
if (is_inactive != m_inactive && !m_pending_active_change)
|
||||
{
|
||||
int delay = settings().get_int(settings_pack::auto_manage_startup);
|
||||
int const delay = settings().get_int(settings_pack::auto_manage_startup);
|
||||
m_inactivity_timer.expires_from_now(seconds(delay));
|
||||
m_inactivity_timer.async_wait(std::bind(&torrent::on_inactivity_tick
|
||||
, shared_from_this(), _1));
|
||||
m_inactivity_timer.async_wait([self](error_code const& ec) {
|
||||
self->wrap(&torrent::on_inactivity_tick, ec); });
|
||||
m_pending_active_change = true;
|
||||
}
|
||||
else if (is_inactive == m_inactive
|
||||
|
|
|
@ -73,7 +73,25 @@ namespace libtorrent
|
|||
TORRENT_ASSERT_PRECOND(t);
|
||||
if (!t) return;
|
||||
session_impl& ses = static_cast<session_impl&>(t->session());
|
||||
ses.get_io_service().dispatch([=] () { (t.get()->*f)(a...); } );
|
||||
ses.get_io_service().dispatch([=,&ses] ()
|
||||
{
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(t.get()->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (system_error const& e) {
|
||||
ses.alerts().emplace_alert<torrent_error_alert>(torrent_handle(m_torrent)
|
||||
, e.code(), e.what());
|
||||
} catch (std::exception const& e) {
|
||||
ses.alerts().emplace_alert<torrent_error_alert>(torrent_handle(m_torrent)
|
||||
, error_code(), e.what());
|
||||
} catch (...) {
|
||||
ses.alerts().emplace_alert<torrent_error_alert>(torrent_handle(m_torrent)
|
||||
, error_code(), "unknown error");
|
||||
}
|
||||
#endif
|
||||
} );
|
||||
}
|
||||
|
||||
template<typename Fun, typename... Args>
|
||||
|
@ -87,15 +105,25 @@ namespace libtorrent
|
|||
// this is the flag to indicate the call has completed
|
||||
bool done = false;
|
||||
|
||||
ses.get_io_service().dispatch([=,&done,&ses] ()
|
||||
std::exception_ptr ex;
|
||||
ses.get_io_service().dispatch([=,&done,&ses,&ex] ()
|
||||
{
|
||||
(t.get()->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
(t.get()->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
#endif
|
||||
std::unique_lock<std::mutex> l(ses.mut);
|
||||
done = true;
|
||||
ses.cond.notify_all();
|
||||
} );
|
||||
|
||||
aux::torrent_wait(done, ses);
|
||||
if (ex) std::rethrow_exception(ex);
|
||||
}
|
||||
|
||||
template<typename Ret, typename Fun, typename... Args>
|
||||
|
@ -110,9 +138,18 @@ namespace libtorrent
|
|||
// this is the flag to indicate the call has completed
|
||||
bool done = false;
|
||||
|
||||
ses.get_io_service().dispatch([=,&r,&done,&ses] ()
|
||||
std::exception_ptr ex;
|
||||
ses.get_io_service().dispatch([=,&r,&done,&ses,&ex] ()
|
||||
{
|
||||
r = (t.get()->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
r = (t.get()->*f)(a...);
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
}
|
||||
#endif
|
||||
std::unique_lock<std::mutex> l(ses.mut);
|
||||
done = true;
|
||||
ses.cond.notify_all();
|
||||
|
@ -120,6 +157,7 @@ namespace libtorrent
|
|||
|
||||
aux::torrent_wait(done, ses);
|
||||
|
||||
if (ex) std::rethrow_exception(ex);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue