1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-25 09:13:06 +00:00

Fix pending_request_data memleak in Session (GTK client) (#2139)

This commit is contained in:
Mike Gelfand 2021-11-13 16:57:22 +03:00 committed by GitHub
parent 7c3f8b5701
commit e144ad6da8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -91,7 +91,7 @@ public:
void add_torrent(tr_torrent* tor, bool do_notify); void add_torrent(tr_torrent* tor, bool do_notify);
bool add_from_url(Glib::ustring const& uri); bool add_from_url(Glib::ustring const& uri);
void send_rpc_request(tr_variant const* request, int tag, std::function<void(tr_variant*)> const& response_func); void send_rpc_request(tr_variant const* request, int64_t tag, std::function<void(tr_variant*)> const& response_func);
void commit_prefs_change(tr_quark key); void commit_prefs_change(tr_quark key);
@ -1631,36 +1631,31 @@ void Session::set_pref(tr_quark const key, double newval)
namespace namespace
{ {
int nextTag = 1; int64_t nextTag = 1;
typedef void (*server_response_func)(Session* core, tr_variant* response, gpointer user_data); typedef void (*server_response_func)(Session* core, tr_variant* response, gpointer user_data);
struct pending_request_data std::map<int64_t, std::function<void(tr_variant*)>> pendingRequests;
{
void* impl;
std::function<void(tr_variant*)> response_func;
};
std::map<int, pending_request_data*> pendingRequests;
bool core_read_rpc_response_idle(tr_variant* response) bool core_read_rpc_response_idle(tr_variant* response)
{ {
int64_t intVal; int64_t tag;
if (tr_variantDictFindInt(response, TR_KEY_tag, &intVal)) if (tr_variantDictFindInt(response, TR_KEY_tag, &tag))
{ {
int const tag = (int)intVal; if (auto const data_it = pendingRequests.find(tag); data_it != pendingRequests.end())
auto const data_it = pendingRequests.find(tag);
if (data_it != pendingRequests.end())
{ {
if (auto const& data = data_it->second; data->response_func) if (auto const& response_func = data_it->second; response_func)
{ {
data->response_func(response); response_func(response);
} }
pendingRequests.erase(data_it); pendingRequests.erase(data_it);
} }
else
{
g_warning("Pending RPC request for tag %" PRId64 " not found", tag);
}
} }
tr_variantFree(response); tr_variantFree(response);
@ -1670,7 +1665,7 @@ bool core_read_rpc_response_idle(tr_variant* response)
void core_read_rpc_response(tr_session* /*session*/, tr_variant* response, void* /*user_data*/) void core_read_rpc_response(tr_session* /*session*/, tr_variant* response, void* /*user_data*/)
{ {
tr_variant* response_copy = new tr_variant(*response); tr_variant* response_copy = new tr_variant(std::move(*response));
tr_variantInitBool(response, false); tr_variantInitBool(response, false);
@ -1679,7 +1674,10 @@ void core_read_rpc_response(tr_session* /*session*/, tr_variant* response, void*
} // namespace } // namespace
void Session::Impl::send_rpc_request(tr_variant const* request, int tag, std::function<void(tr_variant*)> const& response_func) void Session::Impl::send_rpc_request(
tr_variant const* request,
int64_t tag,
std::function<void(tr_variant*)> const& response_func)
{ {
if (session_ == nullptr) if (session_ == nullptr)
{ {
@ -1688,10 +1686,7 @@ void Session::Impl::send_rpc_request(tr_variant const* request, int tag, std::fu
else else
{ {
/* remember this request */ /* remember this request */
auto* const data = new pending_request_data(); pendingRequests.emplace(tag, response_func);
data->impl = this;
data->response_func = response_func;
pendingRequests.emplace(tag, data);
/* make the request */ /* make the request */
#ifdef DEBUG_RPC #ifdef DEBUG_RPC
@ -1703,7 +1698,7 @@ void Session::Impl::send_rpc_request(tr_variant const* request, int tag, std::fu
} }
#endif #endif
tr_rpc_request_exec_json(session_, request, core_read_rpc_response, GINT_TO_POINTER(tag)); tr_rpc_request_exec_json(session_, request, core_read_rpc_response, nullptr);
} }
} }
@ -1713,8 +1708,7 @@ void Session::Impl::send_rpc_request(tr_variant const* request, int tag, std::fu
void Session::port_test() void Session::port_test()
{ {
int const tag = nextTag; auto const tag = nextTag++;
++nextTag;
tr_variant request; tr_variant request;
tr_variantInitDict(&request, 2); tr_variantInitDict(&request, 2);