[evolution-ews/gnome-3-16] Bug 751725 - Enhance thread safety around CamelEwsStore::connection
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews/gnome-3-16] Bug 751725 - Enhance thread safety around CamelEwsStore::connection
- Date: Tue, 30 Jun 2015 20:14:50 +0000 (UTC)
commit 94b3ce3cc8c047c68a2cc5a342a68ecf9ecf3098
Author: Milan Crha <mcrha redhat com>
Date: Tue Jun 30 22:12:23 2015 +0200
Bug 751725 - Enhance thread safety around CamelEwsStore::connection
src/camel/camel-ews-store.c | 112 ++++++++++++++++++++++-----------------
src/server/e-ews-notification.c | 28 ++++++----
2 files changed, 80 insertions(+), 60 deletions(-)
---
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index dec7fa6..acec6bb 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -634,11 +634,19 @@ ews_update_has_ooo_set (CamelSession *session,
CamelEwsStore *ews_store = user_data;
EEwsOofSettings *oof_settings;
EEwsOofState oof_state;
+ EEwsConnection *cnc;
GError *local_error = NULL;
+ cnc = camel_ews_store_ref_connection (ews_store);
+ if (!cnc)
+ return;
+
camel_operation_push_message (cancellable, _("Checking \"Out of Office\" settings"));
- oof_settings = e_ews_oof_settings_new_sync (ews_store->priv->connection, cancellable, &local_error);
+ oof_settings = e_ews_oof_settings_new_sync (cnc, cancellable, &local_error);
+
+ g_clear_object (&cnc);
+
if (local_error != NULL) {
g_propagate_error (error, local_error);
camel_operation_pop_message (cancellable);
@@ -688,6 +696,7 @@ camel_ews_folder_list_update_thread (gpointer user_data)
{
struct ScheduleUpdateData *sud = user_data;
CamelEwsStore *ews_store = sud->ews_store;
+ EEwsConnection *cnc = NULL;
GSList *created = NULL;
GSList *updated = NULL;
GSList *deleted = NULL;
@@ -698,9 +707,13 @@ camel_ews_folder_list_update_thread (gpointer user_data)
if (g_cancellable_is_cancelled (sud->cancellable))
goto exit;
+ cnc = camel_ews_store_ref_connection (ews_store);
+ if (!cnc)
+ goto exit;
+
old_sync_state = camel_ews_store_summary_get_string_val (ews_store->summary, "sync_state", NULL);
if (!e_ews_connection_sync_folder_hierarchy_sync (
- ews_store->priv->connection,
+ cnc,
EWS_PRIORITY_LOW,
old_sync_state,
&new_sync_state,
@@ -739,6 +752,7 @@ camel_ews_folder_list_update_thread (gpointer user_data)
exit:
g_free (old_sync_state);
+ g_clear_object (&cnc);
free_schedule_update_data (sud);
return NULL;
}
@@ -1035,8 +1049,10 @@ start_notifications_thread (gpointer data)
{
struct HandleNotificationsData *hnd = data;
CamelEwsStore *ews_store = hnd->ews_store;
+ EEwsConnection *cnc;
- if (ews_store->priv->connection == NULL)
+ cnc = camel_ews_store_ref_connection (ews_store);
+ if (!cnc)
goto exit;
if (ews_store->priv->listen_notifications) {
@@ -1044,7 +1060,7 @@ start_notifications_thread (gpointer data)
goto exit;
e_ews_connection_enable_notifications_sync (
- ews_store->priv->connection,
+ cnc,
hnd->folders,
&ews_store->priv->subscription_key);
} else {
@@ -1052,7 +1068,7 @@ start_notifications_thread (gpointer data)
goto exit;
e_ews_connection_disable_notifications_sync (
- ews_store->priv->connection,
+ cnc,
ews_store->priv->subscription_key);
ews_store->priv->subscription_key = 0;
@@ -1060,6 +1076,8 @@ start_notifications_thread (gpointer data)
exit:
handle_notifications_data_free (hnd);
+ g_clear_object (&cnc);
+
return NULL;
}
@@ -1087,13 +1105,18 @@ camel_ews_store_handle_notifications (CamelEwsStore *ews_store,
CamelEwsSettings *ews_settings)
{
GThread *thread;
+ EEwsConnection *cnc;
struct HandleNotificationsData *hnd;
- if (ews_store->priv->connection == NULL)
+ cnc = camel_ews_store_ref_connection (ews_store);
+
+ if (!cnc)
return;
- if (!e_ews_connection_satisfies_server_version (ews_store->priv->connection, E_EWS_EXCHANGE_2010_SP1))
+ if (!e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2010_SP1)) {
+ g_clear_object (&cnc);
return;
+ }
hnd = g_new0 (struct HandleNotificationsData, 1);
hnd->ews_store = g_object_ref (ews_store);
@@ -1119,6 +1142,8 @@ camel_ews_store_handle_notifications (CamelEwsStore *ews_store,
camel_folder_info_free (fi);
}
+ g_clear_object (&cnc);
+
thread = g_thread_new (NULL, start_notifications_thread, hnd);
g_thread_unref (thread);
}
@@ -1213,11 +1238,15 @@ ews_connect_sync (CamelService *service,
CAMEL_OFFLINE_STORE (ews_store),
TRUE, cancellable, NULL);
- g_signal_connect_swapped (
- priv->connection,
- "server-notification",
- G_CALLBACK (camel_ews_store_server_notification_cb),
- ews_store);
+ connection = camel_ews_store_ref_connection (ews_store);
+ if (connection) {
+ g_signal_connect_swapped (
+ connection,
+ "server-notification",
+ G_CALLBACK (camel_ews_store_server_notification_cb),
+ ews_store);
+ g_clear_object (&connection);
+ }
}
g_signal_connect_swapped (
@@ -1260,16 +1289,10 @@ stop_pending_updates (CamelEwsStore *ews_store)
UPDATE_UNLOCK (ews_store);
}
-static gboolean
-ews_disconnect_sync (CamelService *service,
- gboolean clean,
- GCancellable *cancellable,
- GError **error)
+static void
+ews_store_unset_connection_locked (CamelEwsStore *ews_store)
{
- CamelEwsStore *ews_store = CAMEL_EWS_STORE (service);
- CamelServiceClass *service_class;
-
- g_mutex_lock (&ews_store->priv->connection_lock);
+ g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
/* TODO cancel all operations in the connection */
if (ews_store->priv->connection != NULL) {
@@ -1281,8 +1304,8 @@ ews_disconnect_sync (CamelService *service,
* our own reference to that CamelSettings instance, or
* better yet avoid connecting signal handlers to it in
* the first place. */
- settings = camel_service_ref_settings (service);
- g_signal_handlers_disconnect_by_data (settings, service);
+ settings = camel_service_ref_settings (CAMEL_SERVICE (ews_store));
+ g_signal_handlers_disconnect_by_data (settings, ews_store);
g_signal_handlers_disconnect_by_func (
ews_store->priv->connection, camel_ews_store_server_notification_cb, ews_store);
@@ -1307,7 +1330,19 @@ ews_disconnect_sync (CamelService *service,
g_object_unref (ews_store->priv->connection);
ews_store->priv->connection = NULL;
}
+}
+static gboolean
+ews_disconnect_sync (CamelService *service,
+ gboolean clean,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelEwsStore *ews_store = CAMEL_EWS_STORE (service);
+ CamelServiceClass *service_class;
+
+ g_mutex_lock (&ews_store->priv->connection_lock);
+ ews_store_unset_connection_locked (ews_store);
g_mutex_unlock (&ews_store->priv->connection_lock);
service_class = CAMEL_SERVICE_CLASS (camel_ews_store_parent_class);
@@ -1781,8 +1816,7 @@ ews_authenticate_sync (CamelService *service,
GSList *foreign_fids, *ff;
g_mutex_lock (&ews_store->priv->connection_lock);
- if (ews_store->priv->connection != NULL)
- g_object_unref (ews_store->priv->connection);
+ ews_store_unset_connection_locked (ews_store);
ews_store->priv->connection = g_object_ref (connection);
g_mutex_unlock (&ews_store->priv->connection_lock);
@@ -1805,10 +1839,7 @@ ews_authenticate_sync (CamelService *service,
g_slist_free_full (foreign_fids, g_free);
} else {
g_mutex_lock (&ews_store->priv->connection_lock);
- if (ews_store->priv->connection != NULL) {
- g_object_unref (ews_store->priv->connection);
- ews_store->priv->connection = NULL;
- }
+ ews_store_unset_connection_locked (ews_store);
g_mutex_unlock (&ews_store->priv->connection_lock);
g_free (new_sync_state);
@@ -3568,26 +3599,9 @@ ews_store_dispose (GObject *object)
ews_store->summary = NULL;
}
- if (ews_store->priv->connection != NULL) {
- g_signal_handlers_disconnect_by_func (
- ews_store->priv->connection, camel_ews_store_server_notification_cb, ews_store);
-
- if (ews_store->priv->listen_notifications) {
- stop_pending_updates (ews_store);
-
- if (ews_store->priv->subscription_key != 0) {
- e_ews_connection_disable_notifications_sync (
- ews_store->priv->connection,
- ews_store->priv->subscription_key);
-
- ews_store->priv->subscription_key = 0;
- }
-
- ews_store->priv->listen_notifications = FALSE;
- }
-
- g_clear_object (&ews_store->priv->connection);
- }
+ g_mutex_lock (&ews_store->priv->connection_lock);
+ ews_store_unset_connection_locked (ews_store);
+ g_mutex_unlock (&ews_store->priv->connection_lock);
g_slist_free_full (ews_store->priv->update_folder_names, g_free);
ews_store->priv->update_folder_names = NULL;
diff --git a/src/server/e-ews-notification.c b/src/server/e-ews-notification.c
index 4576f88..b5f30c1 100644
--- a/src/server/e-ews-notification.c
+++ b/src/server/e-ews-notification.c
@@ -113,20 +113,11 @@ ews_notification_authenticate (SoupSession *session,
EEwsNotification *
e_ews_notification_new (EEwsConnection *connection)
{
- EEwsNotification *notification;
- CamelEwsSettings *ews_settings;
-
g_return_val_if_fail (E_IS_EWS_CONNECTION (connection), NULL);
- notification = g_object_new (
+ return g_object_new (
E_TYPE_EWS_NOTIFICATION,
"connection", connection, NULL);
-
- ews_settings = e_ews_connection_ref_settings (connection);
-
- g_object_unref (ews_settings);
-
- return notification;
}
static void
@@ -774,6 +765,13 @@ e_ews_notification_get_events_sync (EEwsNotification *notification,
return ret;
}
+static void
+ews_notification_cancelled_cb (GCancellable *cancellable,
+ SoupSession *session)
+{
+ soup_session_abort (session);
+}
+
static gpointer
e_ews_notification_get_events_thread (gpointer user_data)
{
@@ -789,14 +787,22 @@ e_ews_notification_get_events_thread (gpointer user_data)
goto exit;
do {
+ gulong handler_id;
+
if (g_cancellable_is_cancelled (td->cancellable))
goto exit;
+ handler_id = g_cancellable_connect (td->cancellable, G_CALLBACK
(ews_notification_cancelled_cb),
+ g_object_ref (td->notification->priv->soup_session), g_object_unref);
+
ret = e_ews_notification_get_events_sync (
td->notification,
subscription_id);
- if (!ret) {
+ if (handler_id > 0)
+ g_cancellable_disconnect (td->cancellable, handler_id);
+
+ if (!ret && !g_cancellable_is_cancelled (td->cancellable)) {
g_debug ("%s: Failed to get notification events (SubscriptionId: '%s')", G_STRFUNC,
subscription_id);
e_ews_notification_unsubscribe_folder_sync (td->notification, subscription_id);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]