[evolution-data-server] Bug #688795 - Crash under e_cal_backend_contacts_start_view()



commit 38621444df0ea243e5722242d8dc2ec11b19894a
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 22 17:13:49 2012 +0100

    Bug #688795 - Crash under e_cal_backend_contacts_start_view()

 .../backends/contacts/e-cal-backend-contacts.c     |   53 ++++++++++++++++----
 1 files changed, 43 insertions(+), 10 deletions(-)
---
diff --git a/calendar/backends/contacts/e-cal-backend-contacts.c b/calendar/backends/contacts/e-cal-backend-contacts.c
index c88885d..1a53655 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -58,12 +58,13 @@ typedef enum
 /* Private part of the ECalBackendContacts structure */
 struct _ECalBackendContactsPrivate {
 
-	GRecMutex rec_mutex;			/* guards 'addressbooks' */
+	GRecMutex rec_mutex;		/* guards 'addressbooks' */
 	GHashTable   *addressbooks;	/* UID -> BookRecord */
 	gboolean      addressbook_loaded;
 
 	EBookClientView *book_view;
-	GHashTable   *tracked_contacts;   /* UID -> ContactRecord */
+	GHashTable *tracked_contacts;	/* UID -> ContactRecord */
+	GRecMutex tracked_contacts_lock;
 
 	GHashTable *zones;
 
@@ -172,9 +173,11 @@ book_record_unref (BookRecord *br)
 			g_signal_handler_disconnect (
 				br->book_client,
 				br->book_client_opened_id);
+		g_rec_mutex_lock (&br->cbc->priv->tracked_contacts_lock);
 		g_hash_table_foreach_remove (
 			br->cbc->priv->tracked_contacts,
 			remove_by_book, br->book_client);
+		g_rec_mutex_unlock (&br->cbc->priv->tracked_contacts_lock);
 
 		g_mutex_clear (&br->lock);
 		g_object_unref (br->cbc);
@@ -506,11 +509,14 @@ contact_record_cb_new (ECalBackendContacts *cbc,
 }
 
 static void
-contact_record_cb_free (ContactRecordCB *cb_data)
+contact_record_cb_free (ContactRecordCB *cb_data,
+			gboolean can_free_result)
 {
-	if (cb_data->as_string)
-		g_slist_foreach (cb_data->result, (GFunc) g_free, NULL);
-	g_slist_free (cb_data->result);
+	if (can_free_result) {
+		if (cb_data->as_string)
+			g_slist_foreach (cb_data->result, (GFunc) g_free, NULL);
+		g_slist_free (cb_data->result);
+	}
 
 	g_free (cb_data);
 }
@@ -617,6 +623,8 @@ contacts_modified_cb (EBookClientView *book_view,
 	EBookClient *book_client = e_book_client_view_get_client (book_view);
 	const GSList *ii;
 
+	g_rec_mutex_lock (&cbc->priv->tracked_contacts_lock);
+
 	for (ii = contacts; ii; ii = ii->next) {
 		EContact *contact = E_CONTACT (ii->data);
 		const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
@@ -638,6 +646,8 @@ contacts_modified_cb (EBookClientView *book_view,
 		e_contact_date_free (birthday);
 		e_contact_date_free (anniversary);
 	}
+
+	g_rec_mutex_unlock (&cbc->priv->tracked_contacts_lock);
 }
 
 static void
@@ -649,6 +659,8 @@ contacts_added_cb (EBookClientView *book_view,
 	EBookClient *book_client = e_book_client_view_get_client (book_view);
 	const GSList *ii;
 
+	g_rec_mutex_lock (&cbc->priv->tracked_contacts_lock);
+
 	/* See if any new contacts have BIRTHDAY or ANNIVERSARY fields */
 	for (ii = contacts; ii; ii = ii->next) {
 		EContact *contact = E_CONTACT (ii->data);
@@ -667,6 +679,8 @@ contacts_added_cb (EBookClientView *book_view,
 		e_contact_date_free (birthday);
 		e_contact_date_free (anniversary);
 	}
+
+	g_rec_mutex_unlock (&cbc->priv->tracked_contacts_lock);
 }
 
 static void
@@ -677,9 +691,13 @@ contacts_removed_cb (EBookClientView *book_view,
 	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
 	const GSList *ii;
 
+	g_rec_mutex_lock (&cbc->priv->tracked_contacts_lock);
+
 	/* Stop tracking these */
 	for (ii = contact_ids; ii; ii = ii->next)
 		g_hash_table_remove (cbc->priv->tracked_contacts, ii->data);
+
+	g_rec_mutex_unlock (&cbc->priv->tracked_contacts_lock);
 }
 
 /************************************************************************************/
@@ -751,7 +769,10 @@ update_tracked_alarms_cb (gpointer user_data)
 
 	g_return_val_if_fail (cbc != NULL, FALSE);
 
+	g_rec_mutex_lock (&cbc->priv->tracked_contacts_lock);
 	g_hash_table_foreach (cbc->priv->tracked_contacts, update_alarm_cb, cbc);
+	g_rec_mutex_unlock (&cbc->priv->tracked_contacts_lock);
+
 	cbc->priv->update_alarms_id = 0;
 
 	return FALSE;
@@ -1074,16 +1095,19 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend,
 		return;
 	}
 
+	g_rec_mutex_lock (&priv->tracked_contacts_lock);
 	record = g_hash_table_lookup (priv->tracked_contacts, real_uid);
 	g_free (real_uid);
 
 	if (!record) {
+		g_rec_mutex_unlock (&priv->tracked_contacts_lock);
 		g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
 		return;
 	}
 
 	if (record->comp_birthday && g_str_has_suffix (uid, BIRTHDAY_UID_EXT)) {
 		*object = e_cal_component_get_as_string (record->comp_birthday);
+		g_rec_mutex_unlock (&priv->tracked_contacts_lock);
 
 		d (g_message ("Return birthday: %s", *object));
 		return;
@@ -1091,11 +1115,14 @@ e_cal_backend_contacts_get_object (ECalBackendSync *backend,
 
 	if (record->comp_anniversary && g_str_has_suffix (uid, ANNIVERSARY_UID_EXT)) {
 		*object = e_cal_component_get_as_string (record->comp_anniversary);
+		g_rec_mutex_unlock (&priv->tracked_contacts_lock);
 
 		d (g_message ("Return anniversary: %s", *object));
 		return;
 	}
 
+	g_rec_mutex_unlock (&priv->tracked_contacts_lock);
+
 	d (g_message ("Returning nothing for uid: %s", uid));
 
 	g_propagate_error (perror, EDC_ERROR (ObjectNotFound));
@@ -1260,12 +1287,14 @@ e_cal_backend_contacts_get_object_list (ECalBackendSync *backend,
 	}
 
 	cb_data = contact_record_cb_new (cbc, sexp, TRUE);
+
+	g_rec_mutex_lock (&priv->tracked_contacts_lock);
 	g_hash_table_foreach (priv->tracked_contacts, contact_record_cb, cb_data);
+	g_rec_mutex_unlock (&priv->tracked_contacts_lock);
+
 	*objects = cb_data->result;
 
-	/* Don't call cb_data_free as that would destroy the results
-	 * in *objects */
-	g_free (cb_data);
+	contact_record_cb_free (cb_data, FALSE);
 }
 
 static void
@@ -1287,10 +1316,12 @@ e_cal_backend_contacts_start_view (ECalBackend *backend,
 
 	cb_data = contact_record_cb_new (cbc, sexp, FALSE);
 
+	g_rec_mutex_lock (&priv->tracked_contacts_lock);
 	g_hash_table_foreach (priv->tracked_contacts, contact_record_cb, cb_data);
 	e_data_cal_view_notify_components_added (query, cb_data->result);
+	g_rec_mutex_unlock (&priv->tracked_contacts_lock);
 
-	contact_record_cb_free (cb_data);
+	contact_record_cb_free (cb_data, TRUE);
 
 	e_data_cal_view_notify_complete (query, NULL /* Success */);
 }
@@ -1334,6 +1365,7 @@ e_cal_backend_contacts_finalize (GObject *object)
 
 	g_object_unref (priv->settings);
 	g_rec_mutex_clear (&priv->rec_mutex);
+	g_rec_mutex_clear (&priv->tracked_contacts_lock);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (e_cal_backend_contacts_parent_class)->finalize (object);
@@ -1374,6 +1406,7 @@ e_cal_backend_contacts_init (ECalBackendContacts *cbc)
 	cbc->priv = E_CAL_BACKEND_CONTACTS_GET_PRIVATE (cbc);
 
 	g_rec_mutex_init (&cbc->priv->rec_mutex);
+	g_rec_mutex_init (&cbc->priv->tracked_contacts_lock);
 
 	cbc->priv->addressbooks = g_hash_table_new_full (
 		(GHashFunc) e_source_hash,



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