[evolution-data-server/gnome-3-30] Deadlock when marking as read message in a search folder



commit 0a093c2f07c263712469f5cf593292cdd957db3c
Author: Milan Crha <mcrha redhat com>
Date:   Mon Nov 19 14:03:47 2018 +0100

    Deadlock when marking as read message in a search folder
    
    There could happen a deadlock when two threads change for example
    message info flags, where one threads holds message info's summary lock
    and is waiting for the info's property lock, which the other thread
    hold's info's property lock and is waiting for the summary lock.
    It's safer to hold summary lock before acquiring the message info's
    lock when anything will be changed in the message info, which didn't
    happen here.
    
    This had been reported downstream at:
    https://bugzilla.redhat.com/show_bug.cgi?id=1649373

 src/camel/camel-folder.c     | 44 +++++++++++++++++++++++++++++++++++++++-----
 src/camel/camel-vee-folder.c |  4 ++++
 2 files changed, 43 insertions(+), 5 deletions(-)
---
diff --git a/src/camel/camel-folder.c b/src/camel/camel-folder.c
index 1ecca75bb..cc6ebd96c 100644
--- a/src/camel/camel-folder.c
+++ b/src/camel/camel-folder.c
@@ -279,25 +279,41 @@ folder_filter (CamelSession *session,
 
        /* Reset junk learn flag so that we don't process it again */
        if (data->junk) {
+               CamelFolderSummary *summary;
+
+               summary = camel_folder_get_folder_summary (data->folder);
+
+               camel_folder_summary_lock (summary);
+
                for (i = 0; i < data->junk->len; i++) {
-                       info = camel_folder_summary_get (camel_folder_get_folder_summary (data->folder), 
data->junk->pdata[i]);
+                       info = camel_folder_summary_get (summary, data->junk->pdata[i]);
                        if (!info)
                                continue;
 
                        camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK_LEARN, 0);
                        g_clear_object (&info);
                }
+
+               camel_folder_summary_unlock (summary);
        }
 
        if (data->notjunk) {
+               CamelFolderSummary *summary;
+
+               summary = camel_folder_get_folder_summary (data->folder);
+
+               camel_folder_summary_lock (summary);
+
                for (i = 0; i < data->notjunk->len; i++) {
-                       info = camel_folder_summary_get (camel_folder_get_folder_summary (data->folder), 
data->notjunk->pdata[i]);
+                       info = camel_folder_summary_get (summary, data->notjunk->pdata[i]);
                        if (!info)
                                continue;
 
                        camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK_LEARN, 0);
                        g_clear_object (&info);
                }
+
+               camel_folder_summary_unlock (summary);
        }
 
        if (data->junk) {
@@ -719,13 +735,19 @@ folder_set_message_flags (CamelFolder *folder,
 
        g_return_val_if_fail (folder->priv->summary != NULL, FALSE);
 
+       camel_folder_summary_lock (folder->priv->summary);
+
        info = camel_folder_summary_get (folder->priv->summary, uid);
-       if (info == NULL)
+       if (info == NULL) {
+               camel_folder_summary_unlock (folder->priv->summary);
                return FALSE;
+       }
 
        res = camel_message_info_set_flags (info, mask, set);
        g_clear_object (&info);
 
+       camel_folder_summary_unlock (folder->priv->summary);
+
        return res;
 }
 
@@ -759,12 +781,18 @@ folder_set_message_user_flag (CamelFolder *folder,
 
        g_return_if_fail (folder->priv->summary != NULL);
 
+       camel_folder_summary_lock (folder->priv->summary);
+
        info = camel_folder_summary_get (folder->priv->summary, uid);
-       if (info == NULL)
+       if (info == NULL) {
+               camel_folder_summary_unlock (folder->priv->summary);
                return;
+       }
 
        camel_message_info_set_user_flag (info, name, value);
        g_clear_object (&info);
+
+       camel_folder_summary_unlock (folder->priv->summary);
 }
 
 static const gchar *
@@ -797,12 +825,18 @@ folder_set_message_user_tag (CamelFolder *folder,
 
        g_return_if_fail (folder->priv->summary != NULL);
 
+       camel_folder_summary_lock (folder->priv->summary);
+
        info = camel_folder_summary_get (folder->priv->summary, uid);
-       if (info == NULL)
+       if (info == NULL) {
+               camel_folder_summary_unlock (folder->priv->summary);
                return;
+       }
 
        camel_message_info_set_user_tag (info, name, value);
        g_clear_object (&info);
+
+       camel_folder_summary_unlock (folder->priv->summary);
 }
 
 static GPtrArray *
diff --git a/src/camel/camel-vee-folder.c b/src/camel/camel-vee-folder.c
index af8850001..b5017d78b 100644
--- a/src/camel/camel-vee-folder.c
+++ b/src/camel/camel-vee-folder.c
@@ -139,6 +139,8 @@ vee_folder_note_added_uid (CamelVeeFolder *vfolder,
 {
        const gchar *vuid;
 
+       camel_folder_summary_lock (CAMEL_FOLDER_SUMMARY (vsummary));
+
        vuid = camel_vee_message_info_data_get_vee_message_uid (added_mi_data);
        if (!camel_folder_summary_check_uid (CAMEL_FOLDER_SUMMARY (vsummary), vuid)) {
                /* add it only if it wasn't in yet */
@@ -158,6 +160,8 @@ vee_folder_note_added_uid (CamelVeeFolder *vfolder,
                if (included_as_changed && changes)
                        camel_folder_change_info_change_uid (changes, vuid);
        }
+
+       camel_folder_summary_unlock (CAMEL_FOLDER_SUMMARY (vsummary));
 }
 
 static void


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