[evolution-mapi] Bug #607744 - Crash on MAPI notification close



commit 006728d1cd3c778a1fd87ddf497a8411d9b9cd70
Author: Milan Crha <mcrha redhat com>
Date:   Fri Feb 5 13:35:28 2010 +0100

    Bug #607744 - Crash on MAPI notification close

 src/camel/camel-mapi-notifications.c           |   78 ++++++++++++++----------
 src/camel/camel-mapi-notifications.h           |    6 +-
 src/camel/camel-mapi-store.c                   |   12 +++-
 src/libexchangemapi/exchange-mapi-connection.c |   19 ++----
 src/libexchangemapi/exchange-mapi-connection.h |    6 +-
 5 files changed, 66 insertions(+), 55 deletions(-)
---
diff --git a/src/camel/camel-mapi-notifications.c b/src/camel/camel-mapi-notifications.c
index 99a2150..3276a8e 100644
--- a/src/camel/camel-mapi-notifications.c
+++ b/src/camel/camel-mapi-notifications.c
@@ -62,44 +62,31 @@ struct mapi_push_notification_msg {
 	guint32 connection; 
 	guint32 event_options;
 	gpointer event_data;
-};
-
-/*Used for spawning threads for event actions
-  like new_mail, folder_created*/
-struct mapi_push_event_action_msg {
-	CamelSessionThreadMsg msg;
 
-	uint64_t fid;
-	uint64_t mid;
-	gpointer data;
+	gint op_id;
 };
 
 static void
-mapi_new_mail_fetch (struct NewMailNotification *event, gpointer data)	
+process_mapi_new_mail_notif (CamelMapiStore *store, struct NewMailNotification *new_mail_notif)
 {
 	struct mapi_SRestriction *res = NULL;
 	guint32 options = 0;
 
-	CamelMapiStore *store = (CamelMapiStore *)data;
-	fetch_items_data *fetch_data = g_new0 (fetch_items_data, 1);
+	fetch_items_data *fetch_data;
 	CamelFolder *folder = NULL;
 	gint info_count = -1;
 	CamelStoreInfo *info;
 	CamelMapiStoreInfo *mapi_info;
-	const gchar *folder_id = exchange_mapi_util_mapi_id_to_string (event->FID);
+	const gchar *folder_id;
 	const gchar *folder_name = NULL;
-	
+
+	g_return_if_fail (store != NULL);
+	g_return_if_fail (new_mail_notif != NULL);
+
 	/* FIXME : Continue only if we are handling a mail object.*/
 	if (0) return;
-	
-	/*Use restriction to fetch the message summary based on MID*/
-	res = g_new0 (struct mapi_SRestriction, 1);
 
-	res->rt = RES_PROPERTY;
-	res->res.resProperty.relop = RES_PROPERTY;
-	res->res.resProperty.ulPropTag = PR_MID;
-	res->res.resProperty.lpProp.ulPropTag = PR_MID;
-	res->res.resProperty.lpProp.value.dbl = event->MID;
+	folder_id = exchange_mapi_util_mapi_id_to_string (new_mail_notif->FID);
 
 	/* Get the folder object */
 
@@ -122,12 +109,21 @@ mapi_new_mail_fetch (struct NewMailNotification *event, gpointer data)
 	if (!folder)
 		return;
 
+	/*Use restriction to fetch the message summary based on MID*/
+	res = g_new0 (struct mapi_SRestriction, 1);
+
+	res->rt = RES_PROPERTY;
+	res->res.resProperty.relop = RES_PROPERTY;
+	res->res.resProperty.ulPropTag = PR_MID;
+	res->res.resProperty.lpProp.ulPropTag = PR_MID;
+	res->res.resProperty.lpProp.value.dbl = new_mail_notif->MID;
+
+	fetch_data = g_new0 (fetch_items_data, 1);
 	fetch_data->changes = camel_folder_change_info_new ();
 	fetch_data->folder = folder;
 
 	CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-	camel_mapi_folder_fetch_summary ((CamelStore *)store, event->FID,
-					 res, NULL, fetch_data, options);
+	camel_mapi_folder_fetch_summary ((CamelStore *)store, new_mail_notif->FID, res, NULL, fetch_data, options);
 	CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
 	
 	camel_folder_summary_touch (folder->summary);
@@ -143,7 +139,7 @@ mapi_new_mail_fetch (struct NewMailNotification *event, gpointer data)
 }
 
 static gint
-mapi_notifications_filter (guint16 type, void *event, void *data)
+mapi_notifications_filter (guint16 type, void *event, void *store)
 {
 	switch(type) {
 	/* -- Folder Events -- */
@@ -168,7 +164,7 @@ mapi_notifications_filter (guint16 type, void *event, void *data)
 	case fnevNewMail|fnevMbit:
 		d_notifications(printf ("Event : New mail\n"));
 		d_notifications(mapidump_newmail (event, "\t"));
-		mapi_new_mail_fetch (event, data);
+		process_mapi_new_mail_notif (store, event);
 		return -1;
 		break;
 	case fnevMbit|fnevObjectCreated:
@@ -233,12 +229,13 @@ mapi_push_notification_listener (CamelSession *session, CamelSessionThreadMsg *m
 	CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
 
 	if (exchange_mapi_events_init ()) {
-		exchange_mapi_events_subscribe (0, m->event_options, m->event_mask,
+		exchange_mapi_events_subscribe (m->event_options, m->event_mask,
 						&m->connection,	mapi_notifications_filter,
 						m->event_data);
 
 		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
 		exchange_mapi_events_monitor (cb_data); /*Blocking call. Don't hold locks here*/
+		exchange_mapi_events_unsubscribe (m->connection);
 	} else 
 		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
 
@@ -248,12 +245,10 @@ mapi_push_notification_listener (CamelSession *session, CamelSessionThreadMsg *m
 static void
 mapi_push_notification_listener_close (CamelSession *session, CamelSessionThreadMsg *msg)
 {
-	/*TODO*/
 }
 
-void
-camel_mapi_notfication_listener_start (CamelMapiStore *store, guint16 mask, 
-				       guint32 options)
+gpointer
+camel_mapi_notification_listener_start (CamelMapiStore *store, guint16 mask, guint32 options)
 {
 	CamelSession *session = ((CamelService *)store)->session;
 	struct mapi_push_notification_msg *mapi_push_notification_msg_op;
@@ -266,5 +261,24 @@ camel_mapi_notfication_listener_start (CamelMapiStore *store, guint16 mask,
 	mapi_push_notification_msg_op->event_mask = mask;
 	mapi_push_notification_msg_op->event_data = store;
 
-	camel_session_thread_queue (session, &mapi_push_notification_msg_op->msg, 0);
+	mapi_push_notification_msg_op->op_id = camel_session_thread_queue (session, &mapi_push_notification_msg_op->msg, 0);
+
+	return mapi_push_notification_msg_op;
+}
+
+/* start_value is a pointer returned from the start function */
+void
+camel_mapi_notification_listener_stop (CamelMapiStore *store, gpointer start_value)
+{
+	struct mapi_push_notification_msg *msg_op;
+	gint op_id;
+
+	g_return_if_fail (store != NULL);
+	g_return_if_fail (start_value != NULL);
+
+	msg_op = start_value;
+	op_id = msg_op->op_id;
+	camel_operation_cancel (msg_op->msg.op);
+
+	camel_session_thread_wait (((CamelService *)store)->session, op_id);
 }
diff --git a/src/camel/camel-mapi-notifications.h b/src/camel/camel-mapi-notifications.h
index 4c72aef..363a416 100644
--- a/src/camel/camel-mapi-notifications.h
+++ b/src/camel/camel-mapi-notifications.h
@@ -28,9 +28,9 @@
 
 G_BEGIN_DECLS
 
-void
-camel_mapi_notfication_listener_start (CamelMapiStore *store, guint16 mask, 
-				       guint32 options);
+gpointer camel_mapi_notification_listener_start (CamelMapiStore *store, guint16 mask, guint32 options);
+void camel_mapi_notification_listener_stop (CamelMapiStore *store, gpointer start_value);
+
 G_END_DECLS
 
 #endif 
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 1a293ba..1c3c157 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -84,6 +84,7 @@ struct _CamelMapiStorePrivate {
 	GHashTable *default_folders; /*Default Type : Folder ID*/
 
 	gboolean folders_synced; /* whether were synced folder list already */
+	gpointer notification_data; /* pointer to a notification data; can be only one */
 };
 
 static CamelOfflineStoreClass *parent_class = NULL;
@@ -233,6 +234,7 @@ static void camel_mapi_store_init(CamelMapiStore *store, CamelMapiStoreClass *kl
 	priv->storage_path = NULL;
 	priv->base_url = NULL;
 	priv->folders_synced = FALSE;
+	priv->notification_data = NULL;
 
 	mapi_store->priv = priv;
 
@@ -420,7 +422,8 @@ mapi_connect(CamelService *service, CamelException *ex)
 
 	CAMEL_SERVICE_REC_LOCK (store, connect_lock);
 
-	camel_mapi_notfication_listener_start (store, event_mask, MAPI_EVENTS_USE_STORE);
+	if (!store->priv->notification_data)
+		store->priv->notification_data = camel_mapi_notification_listener_start (store, event_mask, MAPI_EVENTS_USE_STORE);
 
 	CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
 
@@ -437,11 +440,14 @@ mapi_disconnect(CamelService *service, gboolean clean, CamelException *ex)
 	CamelMapiStore *store = CAMEL_MAPI_STORE (service);
 
 	/* Disconnect from event monitor */
-	exchange_mapi_events_monitor_close ();
+	if (store->priv->notification_data) {
+		camel_mapi_notification_listener_stop (store, store->priv->notification_data);
+		store->priv->notification_data = NULL;
+	}
 
 	/* Close the mapi subsystem */
 	exchange_mapi_connection_close ();
-	
+
 	store->priv->folders_synced = FALSE;
 
 	((CamelOfflineStore *) store)->state = CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL;
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index eae5f67..82fa76b 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -3109,7 +3109,7 @@ exchange_mapi_events_init ()
 }
 
 gboolean
-exchange_mapi_events_subscribe (mapi_id_t *obj_id, guint32 options,
+exchange_mapi_events_subscribe (guint32 options,
 				guint16 event_mask, guint32 *connection,
 				mapi_notify_callback_t callback, gpointer data)
 {
@@ -3139,11 +3139,14 @@ exchange_mapi_events_subscribe (mapi_id_t *obj_id, guint32 options,
 }
 
 gboolean
-exchange_mapi_events_unsubscribe (mapi_object_t *obj, guint32 connection)
+exchange_mapi_events_unsubscribe (guint32 connection)
 {
 	enum MAPISTATUS	retval;
 
-	retval = Unsubscribe(mapi_object_get_session(obj), connection);
+	if (!global_mapi_session)
+		return FALSE;
+
+	retval = Unsubscribe (global_mapi_session, connection);
 
 	return (retval == MAPI_E_SUCCESS);
 }
@@ -3157,16 +3160,6 @@ exchange_mapi_events_monitor (struct mapi_notify_continue_callback_data *cb_data
 	return retval;
 }
 
-void
-exchange_mapi_events_monitor_close ()
-{
-	struct mapi_notify_ctx	*notify_ctx;
-	if (global_mapi_session) {
-		notify_ctx = global_mapi_session->notify_ctx;
-		close (notify_ctx->fd);
-	}
-}
-
 /* Shows error message on the console, and, if error_msg is not NULL, then
    sets it to the similar error message as well. */
 static void
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index 7ef029c..b3d27e7 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -223,13 +223,11 @@ gboolean exchange_mapi_events_init ();
 
 gboolean exchange_mapi_events_monitor (struct mapi_notify_continue_callback_data *cb_data);
 
-void exchange_mapi_events_monitor_close ();
-
-gboolean exchange_mapi_events_subscribe (mapi_id_t *obj_id, guint32 options,
+gboolean exchange_mapi_events_subscribe (guint32 options,
 					 guint16 event_mask, guint32 *connection,
 					 mapi_notify_callback_t callback, gpointer data);
 
-gboolean exchange_mapi_events_unsubscribe (mapi_object_t *obj, guint32 connection);
+gboolean exchange_mapi_events_unsubscribe (guint32 connection);
 
 gboolean
 exchange_mapi_events_subscribe_and_monitor (mapi_id_t *obj_id, guint32 options,



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