[evolution-kolab/ek-wip-porting] E<Cal|Book>BackendKolab: avoid a race condition (fixes #672631)



commit 8aab729174436dd89e4f345db5d989183cd9b35c
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Thu Mar 22 15:49:14 2012 +0100

    E<Cal|Book>BackendKolab: avoid a race condition (fixes #672631)
    
    * the hash table of active book/cal views needs to
      be shared by all Kolab backend instances of the
      same type (calendar/address book)
    * access to the hash table which keeps the views is
      concurrent when starting and stopping views when
      online mode is switched or Evolution is shut down,
      so we must serialize access to it by using a lock

 src/addressbook/e-book-backend-kolab.c |   51 ++++++++++++++++--------
 src/calendar/e-cal-backend-kolab.c     |   65 ++++++++++++++++++++-----------
 2 files changed, 76 insertions(+), 40 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-kolab.c b/src/addressbook/e-book-backend-kolab.c
index a852fe7..2fa8b25 100644
--- a/src/addressbook/e-book-backend-kolab.c
+++ b/src/addressbook/e-book-backend-kolab.c
@@ -52,6 +52,8 @@
 
 static GHashTable *koma_objects = NULL;
 static GMutex *koma_objects_lock = NULL;
+static GHashTable *active_book_views = NULL;
+static GMutex *active_book_views_lock = NULL;
 
 /*----------------------------------------------------------------------------*/
 
@@ -62,7 +64,6 @@ struct _EBookBackendKolabPrivate
 	EBookBackendCache *book_cache;
 	KolabMailAccess *book_koma;
 	gchar *book_uri;
-	GHashTable *active_book_views;
 	gboolean auth_received;
 	GError *mode_switch_err;
 };
@@ -1081,7 +1082,9 @@ e_book_backend_kolab_start_book_view (EBookBackend *backend,
 	self = E_BOOK_BACKEND_KOLAB (backend);
 	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
 
-	bv = g_hash_table_lookup (priv->active_book_views, book_view);
+	g_mutex_lock (active_book_views_lock);
+
+	bv = g_hash_table_lookup (active_book_views, book_view);
 	if (bv != NULL) {
 		g_warning ("%s()[%u] book view already active!",
 		           __func__, __LINE__);
@@ -1089,7 +1092,7 @@ e_book_backend_kolab_start_book_view (EBookBackend *backend,
 	}
 
 	g_object_ref (book_view);
-	g_hash_table_insert (priv->active_book_views,
+	g_hash_table_insert (active_book_views,
 	                     book_view,
 	                     NULL);
 
@@ -1123,17 +1126,21 @@ e_book_backend_kolab_start_book_view (EBookBackend *backend,
 
  exit:
 
-	if (econtact_list != NULL)
-		g_list_free (econtact_list);
-
 	if (tmp_err != NULL) {
 		kolab_util_contact_err_to_edb_err (&notify_err, tmp_err, __func__, __LINE__);
 		g_error_free (tmp_err);
 	}
 
 	e_data_book_view_notify_complete (book_view, notify_err);
+
+	g_mutex_unlock (active_book_views_lock);
+
 	if (notify_err != NULL)
 		g_error_free (notify_err);
+
+	if (econtact_list != NULL)
+		g_list_free (econtact_list);
+
 }
 
 static void
@@ -1150,15 +1157,20 @@ e_book_backend_kolab_stop_book_view (EBookBackend *backend,
 	self = E_BOOK_BACKEND_KOLAB (backend);
 	priv = E_BOOK_BACKEND_KOLAB_PRIVATE (self);
 
-	bv = g_hash_table_lookup (priv->active_book_views, book_view);
+	g_mutex_lock (active_book_views_lock);
+
+	bv = g_hash_table_lookup (active_book_views, book_view);
 	if (bv == NULL) {
 		g_warning ("%s()[%u] book view already stopped!",
 		           __func__, __LINE__);
-		return;
+		goto exit;
 	}
 
 	e_data_book_view_notify_complete (book_view, NULL);
-	g_hash_table_remove (priv->active_book_views, book_view);
+	g_hash_table_remove (active_book_views, book_view);
+
+ exit:
+	g_mutex_unlock (active_book_views_lock);
 }
 
 /*----------------------------------------------------------------------------*/
@@ -1190,16 +1202,25 @@ e_book_backend_kolab_init (EBookBackendKolab *backend)
 		                                      g_free,
 		                                      g_object_unref);
 	g_mutex_unlock (koma_objects_lock);
+	/* active cal views are shared in the same way,
+	 * so we do the housekeeping for them analogous
+	 * to the KolabMailAccess instances
+	 */
+	if (active_book_views_lock == NULL)
+		active_book_views_lock = g_mutex_new ();
+	g_mutex_lock (active_book_views_lock);
+	if (active_book_views == NULL)
+		active_book_views = g_hash_table_new_full (g_direct_hash,
+		                                           g_direct_equal,
+		                                           g_object_unref,
+		                                           NULL);
+	g_mutex_unlock (active_book_views_lock);
 
 	g_debug ("%s()[%u] called.", __func__, __LINE__);
 
 	priv->book_cache = NULL;
 	priv->book_uri = NULL;
 	priv->book_koma = NULL;
-	priv->active_book_views = g_hash_table_new_full (g_direct_hash,
-	                                                 g_direct_equal,
-	                                                 g_object_unref,
-	                                                 NULL);
 	priv->auth_received = FALSE;
 	priv->mode_switch_err = NULL;
 
@@ -1234,10 +1255,6 @@ e_book_backend_kolab_dispose (GObject *object)
 		g_object_unref (priv->book_cache);
 		priv->book_cache = NULL;
 	}
-	if (priv->active_book_views != NULL) {
-		g_hash_table_destroy (priv->active_book_views);
-		priv->active_book_views = NULL;
-	}
 }
 
 static void
diff --git a/src/calendar/e-cal-backend-kolab.c b/src/calendar/e-cal-backend-kolab.c
index 173c020..61937b7 100644
--- a/src/calendar/e-cal-backend-kolab.c
+++ b/src/calendar/e-cal-backend-kolab.c
@@ -52,6 +52,8 @@
 
 static GHashTable *koma_objects = NULL;
 static GMutex *koma_objects_lock = NULL;
+static GHashTable *active_cal_views = NULL;
+static GMutex *active_cal_views_lock = NULL;
 
 /*----------------------------------------------------------------------------*/
 /* forward declarations */
@@ -92,7 +94,6 @@ struct _ECalBackendKolabPrivate {
 	CalMode cal_mode;
 	KolabMailAccess *cal_koma;
 	ECalBackendCache *cal_cache;
-	GHashTable *active_cal_views;
 	gchar *user_email;
 	ECalComponent *default_zone;
 	ECalSourceType source_type;
@@ -1747,15 +1748,17 @@ e_cal_backend_kolab_start_view (ECalBackend *backend,
 	self = E_CAL_BACKEND_KOLAB (backend);
 	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
 
-	cv = g_hash_table_lookup (priv->active_cal_views, view);
+	g_mutex_lock (active_cal_views_lock);
+
+	cv = g_hash_table_lookup (active_cal_views, view);
 	if (cv != NULL) {
 		g_warning ("%s()[%u] cal view already active!",
 		           __func__, __LINE__);
-		return;
+		goto exit;
 	}
 
 	g_object_ref (view);
-	g_hash_table_insert (priv->active_cal_views,
+	g_hash_table_insert (active_cal_views,
 	                     view,
 	                     NULL);
 
@@ -1809,15 +1812,8 @@ e_cal_backend_kolab_start_view (ECalBackend *backend,
 
 	e_data_cal_view_notify_objects_added (view,
 	                                      iCal_objects);
+
  exit:
-	if (iCal_objects != NULL) {
-		g_slist_foreach (iCal_objects, (GFunc) g_free, NULL);
-		g_slist_free (iCal_objects);
-	}
-	if (sourcename != NULL)
-		g_free (sourcename);
-	if (uid_list != NULL)
-		kolab_util_glib_glist_free (uid_list);
 
 	if (tmp_err != NULL) {
 		kolab_util_calendar_err_to_edb_err (&view_err, tmp_err, __func__, __LINE__);
@@ -1825,8 +1821,21 @@ e_cal_backend_kolab_start_view (ECalBackend *backend,
 	}
 
 	e_data_cal_view_notify_complete (view, view_err);
+
+	g_mutex_unlock (active_cal_views_lock);
+
 	if (view_err != NULL)
 		g_error_free (view_err);
+
+	if (iCal_objects != NULL) {
+		g_slist_foreach (iCal_objects, (GFunc) g_free, NULL);
+		g_slist_free (iCal_objects);
+	}
+	if (sourcename != NULL)
+		g_free (sourcename);
+	if (uid_list != NULL)
+		kolab_util_glib_glist_free (uid_list);
+
 }
 
 static void
@@ -1843,15 +1852,20 @@ e_cal_backend_kolab_stop_view (ECalBackend *backend,
 	self = E_CAL_BACKEND_KOLAB (backend);
 	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
 
-	cv = g_hash_table_lookup (priv->active_cal_views, view);
+	g_mutex_lock (active_cal_views_lock);
+
+	cv = g_hash_table_lookup (active_cal_views, view);
 	if (cv == NULL) {
 		g_warning ("%s()[%u] cal view already stopped!",
 		           __func__, __LINE__);
-		return;
+		goto exit;
 	}
 
 	e_data_cal_view_notify_complete (view, NULL);
-	g_hash_table_remove (priv->active_cal_views, view);
+	g_hash_table_remove (active_cal_views, view);
+
+ exit:
+	g_mutex_unlock (active_cal_views_lock);
 }
 
 static void
@@ -1902,6 +1916,19 @@ e_cal_backend_kolab_init (ECalBackendKolab *backend)
 		                                      g_free,
 		                                      g_object_unref);
 	g_mutex_unlock (koma_objects_lock);
+	/* active cal views are shared in the same way,
+	 * so we do the housekeeping for them analogous
+	 * to the KolabMailAccess instances
+	 */
+	if (active_cal_views_lock == NULL)
+		active_cal_views_lock = g_mutex_new ();
+	g_mutex_lock (active_cal_views_lock);
+	if (active_cal_views == NULL)
+		active_cal_views = g_hash_table_new_full (g_direct_hash,
+		                                          g_direct_equal,
+		                                          g_object_unref,
+		                                          NULL);
+	g_mutex_unlock (active_cal_views_lock);
 
 	g_debug ("%s()[%u] called.", __func__, __LINE__);
 
@@ -1913,10 +1940,6 @@ e_cal_backend_kolab_init (ECalBackendKolab *backend)
 	priv->source_type = 0;
 	priv->cal_uri = NULL;
 	priv->mode_switch_err = NULL;
-	priv->active_cal_views = g_hash_table_new_full (g_direct_hash,
-	                                                g_direct_equal,
-	                                                g_object_unref,
-	                                                NULL);
 
 	g_signal_connect (E_BACKEND (backend), "notify::online", G_CALLBACK (cal_backend_kolab_signal_online_cb), NULL);
 } /* e_cal_backend_kolab_init () */
@@ -1944,10 +1967,6 @@ e_cal_backend_kolab_dispose (GObject *object)
 		g_object_unref (priv->cal_cache);
 		priv->cal_cache = NULL;
 	}
-	if (priv->active_cal_views != NULL) {
-		g_hash_table_destroy (priv->active_cal_views);
-		priv->active_cal_views = NULL;
-	}
 
 	G_OBJECT_CLASS (e_cal_backend_kolab_parent_class)->dispose (object);
 } /* e_cal_backend_kolab_dispose () */



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