fix: conform to libcurl requirements to avoid memory leak (#5702)

This commit is contained in:
tearfur 2023-07-06 11:05:03 +08:00 committed by GitHub
parent f83a60830a
commit 2211086338
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 78 additions and 39 deletions

View File

@ -200,6 +200,8 @@ static std::string getConfigDir(int argc, char const** argv)
int tr_main(int argc, char* argv[])
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
tr_variant settings;

View File

@ -30,6 +30,7 @@
#include <libtransmission/tr-getopt.h>
#include <libtransmission/tr-macros.h>
#include <libtransmission/tr-strbuf.h>
#include <libtransmission/utils.h>
#include <libtransmission/version.h>
#include <libtransmission/watchdir.h>
@ -691,9 +692,6 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
sd_notifyf(0, "MAINPID=%d\n", (int)getpid());
/* should go before libevent calls */
tr_net_init();
/* setup event state */
ev_base_ = event_base_new();
@ -941,6 +939,8 @@ void tr_daemon::handle_error(tr_error* error) const
int tr_main(int argc, char* argv[])
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
int ret;

View File

@ -50,6 +50,9 @@ Glib::OptionEntry create_option_entry(Glib::ustring const& long_name, gchar shor
int main(int argc, char** argv)
{
/* init libtransmission */
auto const init_mgr = tr_lib_init();
/* init i18n */
tr_locale_set_global("");
bindtextdomain(AppTranslationDomainName, TRANSMISSIONLOCALEDIR);

View File

@ -113,8 +113,6 @@ unsigned long thread_current_id()
void initEvthreadsOnce()
{
tr_net_init();
evthread_lock_callbacks constexpr LockCbs{
EVTHREAD_LOCK_API_VERSION, EVTHREAD_LOCKTYPE_RECURSIVE, lock_alloc, lock_free, lock_lock, lock_unlock
};

View File

@ -272,8 +272,6 @@ private:
*/
bool initImpl(struct event_base* event_base)
{
tr_net_init();
int const opt_on = 1;
static_assert(AnnounceScope > 0);

View File

@ -11,7 +11,6 @@
#include <cstdint> // SIZE_MAX
#include <cstdlib> // getenv()
#include <cstring> /* strerror() */
#include <ctime> // nanosleep()
#include <iostream>
#include <iterator> // for std::back_inserter
#include <locale>
@ -19,14 +18,12 @@
#include <set>
#include <string>
#include <string_view>
#include <tuple>
#include <vector>
#ifdef _WIN32
#include <windows.h> /* Sleep(), GetEnvironmentVariable() */
#include <shellapi.h> /* CommandLineToArgv() */
#include <ws2tcpip.h> /* WSAStartup() */
#endif
#ifndef _WIN32
@ -36,6 +33,8 @@
#define UTF_CPP_CPLUSPLUS 201703L
#include <utf8.h>
#include <curl/curl.h>
#include <fmt/core.h>
#include <fast_float/fast_float.h>
@ -929,19 +928,36 @@ std::string tr_env_get_string(std::string_view key, std::string_view default_val
// ---
void tr_net_init()
tr_net_init_mgr::tr_net_init_mgr()
{
#ifdef _WIN32
static bool initialized = false;
if (!initialized)
// try to init curl with default settings (currently ssl support + win32 sockets)
// but if that fails, we need to init win32 sockets as a bare minimum
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
initialized = true;
curl_global_init(CURL_GLOBAL_WIN32);
}
#endif
}
tr_net_init_mgr::~tr_net_init_mgr()
{
curl_global_cleanup();
}
std::unique_ptr<tr_net_init_mgr> tr_net_init_mgr::create()
{
if (!initialised)
{
initialised = true;
return std::unique_ptr<tr_net_init_mgr>{ new tr_net_init_mgr };
}
return {};
}
bool tr_net_init_mgr::initialised = false;
std::unique_ptr<tr_net_init_mgr> tr_lib_init()
{
return tr_net_init_mgr::create();
}
// --- mime-type

View File

@ -10,6 +10,7 @@
#include <cstdint> // uint8_t, uint32_t, uint64_t
#include <cstddef> // size_t
#include <ctime> // time_t
#include <memory>
#include <optional>
#include <string>
#include <string_view>
@ -340,4 +341,20 @@ void tr_formatter_get_units(void* dict);
// ---
void tr_net_init();
class tr_net_init_mgr
{
private:
tr_net_init_mgr();
TR_DISABLE_COPY_MOVE(tr_net_init_mgr)
public:
~tr_net_init_mgr();
static std::unique_ptr<tr_net_init_mgr> create();
private:
static bool initialised;
};
/** @brief Initialise libtransmission for each app
* @return A manager object to be kept in scope of main() */
std::unique_ptr<tr_net_init_mgr> tr_lib_init();

View File

@ -134,8 +134,6 @@ private:
void init(struct event_base* event_base)
{
tr_net_init();
auto const path = dirname();
auto const wide_path = tr_win32_utf8_to_native(path);
if (std::empty(wide_path))

View File

@ -160,8 +160,6 @@ public:
explicit Impl(Mediator& mediator_in)
: mediator{ mediator_in }
{
std::call_once(curl_init_flag, curlInit);
if (auto bundle = tr_env_get_string("CURL_CA_BUNDLE"); !std::empty(bundle))
{
curl_ca_bundle = std::move(bundle);
@ -778,19 +776,7 @@ public:
}
}
static inline auto curl_init_flag = std::once_flag{};
std::map<CURL*, uint64_t /*tr_time_msec()*/> paused_easy_handles;
static void curlInit()
{
// try to enable ssl for https support;
// but if that fails, try a plain vanilla init
if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK)
{
curl_global_init(0);
}
}
};
tr_web::tr_web(Mediator& mediator)

View File

@ -10,6 +10,8 @@
int main(int argc, char** argv)
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
return NSApplicationMain(argc, (char const**)argv);

View File

@ -662,6 +662,8 @@ void Application::onNotificationActionInvoked(quint32 /* notification_id */, QSt
int tr_main(int argc, char** argv)
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
InteropHelper::initialize();

View File

@ -32,9 +32,8 @@ class AnnouncerUdpTest : public ::testing::Test
private:
void SetUp() override
{
tr_net_init();
::testing::Test::SetUp();
init_mgr_ = tr_lib_init();
tr_timeUpdate(time(nullptr));
}
@ -288,6 +287,8 @@ protected:
return timer;
}
std::unique_ptr<tr_net_init_mgr> init_mgr_;
// https://www.bittorrent.org/beps/bep_0015.html
static auto constexpr ProtocolId = uint64_t{ 0x41727101980ULL };
static auto constexpr ConnectAction = uint32_t{ 0 };

View File

@ -15,6 +15,7 @@
#include <libtransmission/file.h>
#include <libtransmission/timer-ev.h>
#include <libtransmission/utils.h>
#include <libtransmission/session-thread.h> // for tr_evthread_init();
#include "gtest/gtest.h"
@ -388,6 +389,8 @@ protected:
{
SandboxedTest::SetUp();
init_mgr_ = tr_lib_init();
tr_session_thread::tr_evthread_init();
event_base_ = event_base_new();
}
@ -402,6 +405,8 @@ protected:
struct event_base* event_base_ = nullptr;
std::unique_ptr<tr_net_init_mgr> init_mgr_;
// Arbitrary values. Several tests requires socket/port values
// to be provided but they aren't central to the tests, so they're
// declared here with "Arbitrary" in the name to make that clear.

View File

@ -530,6 +530,8 @@ protected:
{
SandboxedTest::SetUp();
init_mgr_ = tr_lib_init();
auto callback = [this](tr_torrent* tor, bool /*aborted*/)
{
auto verified_lock = std::scoped_lock(verified_mutex_);
@ -554,6 +556,8 @@ private:
std::mutex verified_mutex_;
std::condition_variable verified_cv_;
std::vector<tr_torrent*> verified_;
std::unique_ptr<tr_net_init_mgr> init_mgr_;
};
} // namespace test

View File

@ -53,10 +53,13 @@ private:
std::shared_ptr<struct event_base> ev_base_;
std::unique_ptr<libtransmission::TimerMaker> timer_maker_;
std::unique_ptr<tr_net_init_mgr> init_mgr_;
protected:
void SetUp() override
{
SandboxedTest::SetUp();
init_mgr_ = tr_lib_init();
ev_base_.reset(event_base_new(), event_base_free);
timer_maker_ = std::make_unique<libtransmission::EvTimerMaker>(ev_base_.get());
Watchdir::set_generic_rescan_interval(GenericRescanInterval);

View File

@ -3290,6 +3290,8 @@ static void getHostAndPortAndRpcUrl(int* argc, char** argv, std::string* host, i
int tr_main(int argc, char* argv[])
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
auto config = Config{};

View File

@ -398,6 +398,8 @@ void doScrape(tr_torrent_metainfo const& metainfo)
int tr_main(int argc, char* argv[])
{
auto const init_mgr = tr_lib_init();
tr_locale_set_global("");
tr_logSetQueueEnabled(false);