[evolution-data-server/gnome-3-18] Bug 702127 - Crash under cal_backend_store_save_cache_now()



commit 25ea5b2fcfd240a5d70973be4fd27b65fbe86bd0
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 19 08:21:00 2015 +0100

    Bug 702127 - Crash under cal_backend_store_save_cache_now()

 calendar/libedata-cal/e-cal-backend-store.c |   57 +++++++++++++++++++++++++--
 1 files changed, 53 insertions(+), 4 deletions(-)
---
diff --git a/calendar/libedata-cal/e-cal-backend-store.c b/calendar/libedata-cal/e-cal-backend-store.c
index 3fbce5f..acde6d7 100644
--- a/calendar/libedata-cal/e-cal-backend-store.c
+++ b/calendar/libedata-cal/e-cal-backend-store.c
@@ -363,21 +363,60 @@ cal_backend_store_save_cache_now (ECalBackendStore *store,
        if (g_rename (tmpfile, store->priv->cache_file_name) != 0)
                g_unlink (tmpfile);
 
+       store->priv->dirty = FALSE;
+
 error:
        g_rw_lock_reader_unlock (&store->priv->lock);
        g_free (tmpfile);
        g_free (data);
 }
 
+static void
+cal_backend_store_toggle_ref_cb (gpointer data,
+                                GObject *object,
+                                gboolean is_last_ref)
+{
+       ECalBackendStore *store;
+
+       g_return_if_fail (E_IS_CAL_BACKEND_STORE (object));
+
+       if (!is_last_ref)
+               return;
+
+       store = E_CAL_BACKEND_STORE (object);
+
+       g_mutex_lock (&store->priv->save_timeout_lock);
+       g_object_ref (store);
+       g_object_remove_toggle_ref (G_OBJECT (store), cal_backend_store_toggle_ref_cb, NULL);
+       store->priv->dirty = TRUE;
+       store->priv->save_timeout_id = 0;
+       g_mutex_unlock (&store->priv->save_timeout_lock);
+
+       g_object_unref (store);
+}
+
 static gboolean
 cal_backend_store_save_cache_timeout_cb (gpointer user_data)
 {
        ECalBackendStore *store;
+       GSource *source;
        GList *timezones_to_save;
 
+       source = g_main_current_source ();
+       if (g_source_is_destroyed (source))
+               return FALSE;
+
        store = E_CAL_BACKEND_STORE (user_data);
 
        g_mutex_lock (&store->priv->save_timeout_lock);
+       if (store->priv->save_timeout_id != g_source_get_id (source)) {
+               g_mutex_unlock (&store->priv->save_timeout_lock);
+               return FALSE;
+       }
+
+       g_object_ref (store);
+
+       g_object_remove_toggle_ref (G_OBJECT (store), cal_backend_store_toggle_ref_cb, NULL);
        store->priv->save_timeout_id = 0;
        timezones_to_save = store->priv->timezones_to_save;
        store->priv->timezones_to_save = NULL;
@@ -389,6 +428,8 @@ cal_backend_store_save_cache_timeout_cb (gpointer user_data)
                timezones_to_save,
                (GDestroyNotify) cal_backend_store_free_zone);
 
+       g_object_unref (store);
+
        return FALSE;
 }
 
@@ -420,8 +461,12 @@ cal_backend_store_save_cache (ECalBackendStore *store)
 
        g_mutex_lock (&store->priv->save_timeout_lock);
 
-       if (store->priv->save_timeout_id > 0)
+       if (store->priv->save_timeout_id > 0) {
                g_source_remove (store->priv->save_timeout_id);
+               g_object_remove_toggle_ref (G_OBJECT (store), cal_backend_store_toggle_ref_cb, NULL);
+       }
+
+       g_object_add_toggle_ref (G_OBJECT (store), cal_backend_store_toggle_ref_cb, NULL);
 
        store->priv->save_timeout_id = e_named_timeout_add_seconds (
                IDLE_SAVE_TIMEOUT_SECONDS,
@@ -526,9 +571,13 @@ cal_backend_store_dispose (GObject *object)
 
        /* If a save is scheduled, cancel it and save now. */
        g_mutex_lock (&priv->save_timeout_lock);
-       if (priv->save_timeout_id > 0) {
-               g_source_remove (priv->save_timeout_id);
-               priv->save_timeout_id = 0;
+       if (priv->save_timeout_id > 0 || priv->dirty) {
+               if (priv->save_timeout_id > 0) {
+                       g_object_remove_toggle_ref (object, cal_backend_store_toggle_ref_cb, NULL);
+                       g_source_remove (priv->save_timeout_id);
+                       priv->save_timeout_id = 0;
+               }
+
                timezones_to_save = priv->timezones_to_save;
                priv->timezones_to_save = NULL;
                save_needed = TRUE;


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