summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2015-11-19 08:21:00 +0100
committerMilan Crha <mcrha@redhat.com>2015-11-19 08:21:50 +0100
commit25ea5b2fcfd240a5d70973be4fd27b65fbe86bd0 (patch)
treeb6a153dcf1eea5ace15a0eb244f6eca2668a0f82
parentf071e7a326485926323a85c3ed6b48b86437fb3a (diff)
downloadevolution-data-server-25ea5b2fcfd240a5d70973be4fd27b65fbe86bd0.tar.gz
Bug 702127 - Crash under cal_backend_store_save_cache_now()
-rw-r--r--calendar/libedata-cal/e-cal-backend-store.c57
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 3fbce5fb7..acde6d76d 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;