[evolution-data-server] [Camel] Folder summary can be leaked after its folder is freed



commit 1ec80cb8a8834443cfce50c3a1d05c8a0eee259f
Author: Milan Crha <mcrha redhat com>
Date:   Thu Aug 25 21:52:58 2016 +0200

    [Camel] Folder summary can be leaked after its folder is freed
    
    The CamelFolerSummary's cfs_try_release_memory() timeout schedule
    added a reference to the summary, which made it alive ad infinity.
    Use GWeakRef for this instead, thus even the timeout source removal
    in the summary's dispose works.

 camel/camel-folder-summary.c |   46 ++++++++++++++++++++++++++++++++++-------
 1 files changed, 38 insertions(+), 8 deletions(-)
---
diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c
index a063e1d..eb46cfe 100644
--- a/camel/camel-folder-summary.c
+++ b/camel/camel-folder-summary.c
@@ -2126,13 +2126,36 @@ remove_cache (CamelSession *session,
        summary->priv->cache_load_time = time (NULL);
 }
 
+static void
+cfs_free_weakref (gpointer ptr)
+{
+       GWeakRef *weakref = ptr;
+
+       if (weakref) {
+               g_weak_ref_set (weakref, NULL);
+               g_weak_ref_clear (weakref);
+               g_free (weakref);
+       }
+}
+
 static gboolean
-cfs_try_release_memory (CamelFolderSummary *summary)
+cfs_try_release_memory (gpointer user_data)
 {
+       GWeakRef *weakref = user_data;
+       CamelFolderSummary *summary;
        CamelStore *parent_store;
        CamelSession *session;
        gchar *description;
 
+       g_return_val_if_fail (weakref != NULL, FALSE);
+
+       summary = g_weak_ref_get (weakref);
+
+       if (!summary)
+               return FALSE;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), FALSE);
+
        /* If folder is freed or if the cache is nil then clean up */
        if (!summary->priv->folder ||
            !g_hash_table_size (summary->priv->loaded_infos) ||
@@ -2144,8 +2167,10 @@ cfs_try_release_memory (CamelFolderSummary *summary)
                return FALSE;
        }
 
-       if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP)
+       if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP) {
+               g_object_unref (summary);
                return TRUE;
+       }
 
        parent_store = camel_folder_get_parent_store (summary->priv->folder);
        if (!parent_store) {
@@ -2175,8 +2200,8 @@ cfs_try_release_memory (CamelFolderSummary *summary)
        camel_session_submit_job (
                session, description,
                (CamelSessionCallback) remove_cache,
-               g_object_ref (summary),
-               (GDestroyNotify) g_object_unref);
+               /* Consumes the reference of the 'summary'. */
+               summary, g_object_unref);
 
        g_object_unref (session);
        g_free (description);
@@ -2202,10 +2227,15 @@ cfs_schedule_info_release_timer (CamelFolderSummary *summary)
 
                /* FIXME[disk-summary] LRU please and not timeouts */
                if (can_do) {
-                       summary->priv->timeout_handle = g_timeout_add_seconds (
-                               SUMMARY_CACHE_DROP,
-                               (GSourceFunc) cfs_try_release_memory,
-                               g_object_ref (summary));
+                       GWeakRef *weakref;
+
+                       weakref = g_new0 (GWeakRef, 1);
+                       g_weak_ref_init (weakref, summary);
+
+                       summary->priv->timeout_handle = g_timeout_add_seconds_full (
+                               G_PRIORITY_DEFAULT, SUMMARY_CACHE_DROP,
+                               cfs_try_release_memory,
+                               weakref, cfs_free_weakref);
                        g_source_set_name_by_id (
                                summary->priv->timeout_handle,
                                "[camel] cfs_try_release_memory");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]