Commit 0a093c2f authored by Milan Crha's avatar Milan Crha

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
parent c4ffe298
......@@ -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 *
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment