summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2018-11-19 14:03:47 +0100
committerMilan Crha <mcrha@redhat.com>2018-11-19 14:03:47 +0100
commitfd0753b23de7e0e4c8a7731a21aa20b09924ab7f (patch)
tree24bfa74d4532b239144f7ffbe3a0983dfabfee7a
parenta1dd05340f7c4b14626280543b4c7a67621bec3c (diff)
downloadevolution-data-server-fd0753b23de7e0e4c8a7731a21aa20b09924ab7f.tar.gz
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
-rw-r--r--src/camel/camel-folder.c44
-rw-r--r--src/camel/camel-vee-folder.c4
2 files changed, 43 insertions, 5 deletions
diff --git a/src/camel/camel-folder.c b/src/camel/camel-folder.c
index abece0c9f..c017bc365 100644
--- a/src/camel/camel-folder.c
+++ b/src/camel/camel-folder.c
@@ -285,25 +285,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) {
@@ -749,13 +765,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;
}
@@ -789,12 +811,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 *
@@ -827,12 +855,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 aae394c7c..383e92385 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