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
1 changed files with 28 additions and 18 deletions

View File

@ -33,13 +33,6 @@ static_assert(TR_AF_INET6 == 1);
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 };
return map[type];
}
@ -50,6 +43,10 @@ auto constexpr IPQueryServices = std::array{ std::array{ "https://ip4.transmissi
auto constexpr UpkeepInterval = 30min;
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
@ -147,6 +144,8 @@ tr_global_ip_cache::tr_global_ip_cache(Mediator& mediator_in)
upkeep_timers_[i]->set_callback(cb);
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)
@ -161,10 +160,15 @@ tr_global_ip_cache::~tr_global_ip_cache()
global_addr_mutex_[TR_AF_INET], global_addr_mutex_[TR_AF_INET6],
source_addr_mutex_[TR_AF_INET], source_addr_mutex_[TR_AF_INET6] };
TR_ASSERT(std::all_of(
std::begin(is_updating_),
std::end(is_updating_),
[](is_updating_t const& v) { return v == is_updating_t::ABORT; }));
if (std::all_of(
std::begin(is_updating_),
std::end(is_updating_),
[](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
@ -238,7 +242,13 @@ void tr_global_ip_cache::update_global_addr(tr_address_type type) noexcept
tr_web::FetchOptions::IPProtocol::V6 };
auto options = tr_web::FetchOptions{ IPQueryServices[type][ix_service_[type]],
[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 };
options.ip_proto = IPProtocolMap[type];
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
if (!success && ++ix_service_[type] < std::size(IPQueryServices[type]))
{
update_global_addr(type);
return;
}
if (!success)
{
if (++ix_service_[type] < std::size(IPQueryServices[type]))
{
update_global_addr(type);
return;
}
tr_logAddDebug(fmt::format("Couldn't obtain global {} address", protocol));
unset_global_addr(type);
upkeep_timers_[type]->set_interval(RetryUpkeepInterval);