From cbbc98b50d4294f68b29358fe8801dafabdf0798 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 13 Aug 2018 18:18:51 +0200 Subject: [PATCH] Make FlatpakRemoteState refcounted This is needed to fix a memory leak Closes: #1964 Approved by: mwleeds --- app/flatpak-builtins-ls-remote.c | 2 +- common/flatpak-dir-private.h | 6 ++++-- common/flatpak-dir.c | 36 +++++++++++++++++++++++--------- common/flatpak-transaction.c | 2 +- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/app/flatpak-builtins-ls-remote.c b/app/flatpak-builtins-ls-remote.c index 48174622..7cecdf15 100644 --- a/app/flatpak-builtins-ls-remote.c +++ b/app/flatpak-builtins-ls-remote.c @@ -62,7 +62,7 @@ static void remote_dir_pair_free (RemoteDirPair *pair) { g_free (pair->remote_name); - flatpak_remote_state_free (pair->state); + flatpak_remote_state_unref (pair->state); g_object_unref (pair->dir); g_free (pair); } diff --git a/common/flatpak-dir-private.h b/common/flatpak-dir-private.h index 3a868f9a..a86fd36e 100644 --- a/common/flatpak-dir-private.h +++ b/common/flatpak-dir-private.h @@ -91,9 +91,11 @@ typedef struct GError *summary_fetch_error; GVariant *metadata; GError *metadata_fetch_error; + int refcount; } FlatpakRemoteState; -void flatpak_remote_state_free (FlatpakRemoteState *remote_state); +FlatpakRemoteState *flatpak_remote_state_ref (FlatpakRemoteState *remote_state); +void flatpak_remote_state_unref (FlatpakRemoteState *remote_state); gboolean flatpak_remote_state_ensure_summary (FlatpakRemoteState *self, GError **error); gboolean flatpak_remote_state_ensure_metadata (FlatpakRemoteState *self, @@ -122,7 +124,7 @@ GVariant *flatpak_remote_state_lookup_sparse_cache (FlatpakRemoteState *self, G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDir, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDeploy, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRelated, flatpak_related_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemoteState, flatpak_remote_state_free) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemoteState, flatpak_remote_state_unref) typedef struct { diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index d9de54dc..a07f70e7 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -198,21 +198,37 @@ get_config_dir_location (void) static FlatpakRemoteState * flatpak_remote_state_new (void) { - return g_new0 (FlatpakRemoteState, 1); + FlatpakRemoteState *state = g_new0 (FlatpakRemoteState, 1); + state->refcount = 1; + return state; +} + +FlatpakRemoteState * +flatpak_remote_state_ref (FlatpakRemoteState *remote_state) +{ + g_assert (remote_state->refcount > 0); + remote_state->refcount++; + return remote_state; } void -flatpak_remote_state_free (FlatpakRemoteState *remote_state) +flatpak_remote_state_unref (FlatpakRemoteState *remote_state) { - g_free (remote_state->remote_name); - g_free (remote_state->collection_id); - g_clear_pointer (&remote_state->summary, g_variant_unref); - g_clear_pointer (&remote_state->summary_sig_bytes, g_bytes_unref); - g_clear_error (&remote_state->summary_fetch_error); - g_clear_pointer (&remote_state->metadata, g_variant_unref); - g_clear_error (&remote_state->metadata_fetch_error); + g_assert (remote_state->refcount > 0); + remote_state->refcount--; - g_free (remote_state); + if (remote_state->refcount == 0) + { + g_free (remote_state->remote_name); + g_free (remote_state->collection_id); + g_clear_pointer (&remote_state->summary, g_variant_unref); + g_clear_pointer (&remote_state->summary_sig_bytes, g_bytes_unref); + g_clear_error (&remote_state->summary_fetch_error); + g_clear_pointer (&remote_state->metadata, g_variant_unref); + g_clear_error (&remote_state->metadata_fetch_error); + + g_free (remote_state); + } } gboolean diff --git a/common/flatpak-transaction.c b/common/flatpak-transaction.c index 094c579b..1bc09c5a 100644 --- a/common/flatpak-transaction.c +++ b/common/flatpak-transaction.c @@ -785,7 +785,7 @@ flatpak_transaction_init (FlatpakTransaction *self) FlatpakTransactionPrivate *priv = flatpak_transaction_get_instance_private (self); priv->last_op_for_ref = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - priv->remote_states = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) flatpak_remote_state_free); + priv->remote_states = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) flatpak_remote_state_unref); priv->added_origin_remotes = g_ptr_array_new_with_free_func (g_free); priv->extra_dependency_dirs = g_ptr_array_new_with_free_func (g_object_unref); }