1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-02-23 14:40:43 +00:00

fix: assert failure when Transmission quit with pending IP queries (#5721)

This commit is contained in:
tearfur 2023-07-05 05:33:58 +08:00 committed by GitHub
parent 56b27057fd
commit 449da2b53e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -33,13 +33,6 @@ static_assert(TR_AF_INET6 == 1);
auto TR_CONSTEXPR23 protocol_str(tr_address_type type) noexcept auto TR_CONSTEXPR23 protocol_str(tr_address_type type) noexcept
{ {
/* TODO: very slight performance nit
* - If upgrading to C++20, change Map to a consteval lambda:
* static auto Map = []() consteval { return std::array{ "IPv4"sv, "IPv6"sv }; };
* - If upgrading to C++23, change Map to static constexpr
*
* Ref: https://wg21.link/p2647r1
*/
static auto TR_CONSTEXPR23 map = std::array{ "IPv4"sv, "IPv6"sv }; static auto TR_CONSTEXPR23 map = std::array{ "IPv4"sv, "IPv6"sv };
return map[type]; return map[type];
} }
@ -50,6 +43,10 @@ auto constexpr IPQueryServices = std::array{ std::array{ "https://ip4.transmissi
auto constexpr UpkeepInterval = 30min; auto constexpr UpkeepInterval = 30min;
auto constexpr RetryUpkeepInterval = 30s; auto constexpr RetryUpkeepInterval = 30s;
// Normally there should only ever be 1 cache instance during the entire program execution
// This is a counter only to cater for SessionTest.honorsSettings
std::size_t cache_exists = 0;
} // namespace } // namespace
namespace namespace
@ -147,6 +144,8 @@ tr_global_ip_cache::tr_global_ip_cache(Mediator& mediator_in)
upkeep_timers_[i]->set_callback(cb); upkeep_timers_[i]->set_callback(cb);
start_timer(type, UpkeepInterval); start_timer(type, UpkeepInterval);
} }
++cache_exists;
} }
std::unique_ptr<tr_global_ip_cache> tr_global_ip_cache::create(tr_global_ip_cache::Mediator& mediator_in) std::unique_ptr<tr_global_ip_cache> tr_global_ip_cache::create(tr_global_ip_cache::Mediator& mediator_in)
@ -161,10 +160,15 @@ tr_global_ip_cache::~tr_global_ip_cache()
global_addr_mutex_[TR_AF_INET], global_addr_mutex_[TR_AF_INET6], global_addr_mutex_[TR_AF_INET], global_addr_mutex_[TR_AF_INET6],
source_addr_mutex_[TR_AF_INET], source_addr_mutex_[TR_AF_INET6] }; source_addr_mutex_[TR_AF_INET], source_addr_mutex_[TR_AF_INET6] };
TR_ASSERT(std::all_of( if (std::all_of(
std::begin(is_updating_), std::begin(is_updating_),
std::end(is_updating_), std::end(is_updating_),
[](is_updating_t const& v) { return v == is_updating_t::ABORT; })); [](is_updating_t const& v) { return v == is_updating_t::ABORT; }))
{
tr_logAddDebug("Destructed while some global IP queries were pending.");
}
--cache_exists;
} }
bool tr_global_ip_cache::try_shutdown() noexcept bool tr_global_ip_cache::try_shutdown() noexcept
@ -238,7 +242,13 @@ void tr_global_ip_cache::update_global_addr(tr_address_type type) noexcept
tr_web::FetchOptions::IPProtocol::V6 }; tr_web::FetchOptions::IPProtocol::V6 };
auto options = tr_web::FetchOptions{ IPQueryServices[type][ix_service_[type]], auto options = tr_web::FetchOptions{ IPQueryServices[type][ix_service_[type]],
[this, type](tr_web::FetchResponse const& response) [this, type](tr_web::FetchResponse const& response)
{ this->on_response_ip_query(type, response); }, {
// Check to avoid segfault
if (cache_exists != 0)
{
this->on_response_ip_query(type, response);
}
},
nullptr }; nullptr };
options.ip_proto = IPProtocolMap[type]; options.ip_proto = IPProtocolMap[type];
options.sndbuf = 4096; options.sndbuf = 4096;
@ -312,14 +322,14 @@ void tr_global_ip_cache::on_response_ip_query(tr_address_type type, tr_web::Fetc
} }
// Try next IP query URL // Try next IP query URL
if (!success && ++ix_service_[type] < std::size(IPQueryServices[type])) if (!success)
{
if (++ix_service_[type] < std::size(IPQueryServices[type]))
{ {
update_global_addr(type); update_global_addr(type);
return; return;
} }
if (!success)
{
tr_logAddDebug(fmt::format("Couldn't obtain global {} address", protocol)); tr_logAddDebug(fmt::format("Couldn't obtain global {} address", protocol));
unset_global_addr(type); unset_global_addr(type);
upkeep_timers_[type]->set_interval(RetryUpkeepInterval); upkeep_timers_[type]->set_interval(RetryUpkeepInterval);