[evolution] Make sure message_list_folder_changed() is called from the main/UI thread
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Make sure message_list_folder_changed() is called from the main/UI thread
- Date: Wed, 3 Oct 2018 14:57:25 +0000 (UTC)
commit cc222b59f6004441e480e8ca36441445be61e7e2
Author: Milan Crha <mcrha redhat com>
Date: Wed Oct 3 16:55:16 2018 +0200
Make sure message_list_folder_changed() is called from the main/UI thread
The function can call (indirectly) gtk+ functions, which are supposed
to be run in the main/UI thread only, thus even the CamelFolder::changed
signal is usually delivered in the main thread it could sometimes
happen that the signal had been delivered in a different thread, which
could cause a crash.
Reported downstream at:
https://bugzilla.redhat.com/show_bug.cgi?id=1635465
src/mail/message-list.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 3 deletions(-)
---
diff --git a/src/mail/message-list.c b/src/mail/message-list.c
index e364b2d97b..70b6a76f17 100644
--- a/src/mail/message-list.c
+++ b/src/mail/message-list.c
@@ -4898,8 +4898,8 @@ mail_folder_hide_by_flag (CamelFolder *folder,
static void
message_list_folder_changed (CamelFolder *folder,
- CamelFolderChangeInfo *changes,
- MessageList *message_list)
+ CamelFolderChangeInfo *changes,
+ MessageList *message_list)
{
CamelFolderChangeInfo *altered_changes = NULL;
ETreeModel *tree_model;
@@ -4908,6 +4908,10 @@ message_list_folder_changed (CamelFolder *folder,
gboolean hide_deleted;
gint i;
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+ g_return_if_fail (changes != NULL);
+ g_return_if_fail (IS_MESSAGE_LIST (message_list));
+
if (message_list->priv->destroyed)
return;
@@ -4976,6 +4980,71 @@ message_list_folder_changed (CamelFolder *folder,
camel_folder_change_info_free (altered_changes);
}
+typedef struct _FolderChangedData {
+ GWeakRef *folder; /* CamelFolder * */
+ CamelFolderChangeInfo *changes;
+ GWeakRef *message_list; /* MessageList * */
+} FolderChangedData;
+
+static void
+folder_changed_data_free (gpointer ptr)
+{
+ FolderChangedData *fcd = ptr;
+
+ if (fcd) {
+ e_weak_ref_free (fcd->folder);
+ e_weak_ref_free (fcd->message_list);
+ camel_folder_change_info_free (fcd->changes);
+ g_free (fcd);
+ }
+}
+
+static gboolean
+message_list_folder_changed_timeout_cb (gpointer user_data)
+{
+ FolderChangedData *fcd = user_data;
+ CamelFolder *folder;
+ MessageList *message_list;
+
+ g_return_val_if_fail (fcd != NULL, FALSE);
+
+ folder = g_weak_ref_get (fcd->folder);
+ message_list = g_weak_ref_get (fcd->message_list);
+
+ if (folder && message_list)
+ message_list_folder_changed (folder, fcd->changes, message_list);
+
+ g_clear_object (&message_list);
+ g_clear_object (&folder);
+
+ return FALSE;
+}
+
+static void
+message_list_folder_changed_cb (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ MessageList *message_list)
+{
+ if (message_list->priv->destroyed)
+ return;
+
+ if (e_util_is_main_thread (g_thread_self ())) {
+ message_list_folder_changed (folder, changes, message_list);
+ } else {
+ FolderChangedData *fcd;
+
+ fcd = g_new0 (FolderChangedData, 1);
+ fcd->folder = e_weak_ref_new (folder);
+ fcd->changes = camel_folder_change_info_copy (changes);
+ fcd->message_list = e_weak_ref_new (message_list);
+
+ /* Just to have it called in the main/UI thread */
+ g_timeout_add_full (G_PRIORITY_DEFAULT, 1,
+ message_list_folder_changed_timeout_cb,
+ fcd, folder_changed_data_free);
+ }
+}
+
CamelFolder *
message_list_ref_folder (MessageList *message_list)
{
@@ -5115,7 +5184,7 @@ message_list_set_folder (MessageList *message_list,
handler_id = g_signal_connect (
folder, "changed",
- G_CALLBACK (message_list_folder_changed),
+ G_CALLBACK (message_list_folder_changed_cb),
message_list);
message_list->priv->folder_changed_handler_id = handler_id;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]