summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2011-10-18 20:12:29 +0200
committerMilan Crha <mcrha@redhat.com>2011-10-18 20:12:29 +0200
commit994a77156da4eead849887e7699c8bcff580c8ba (patch)
tree901420203ebacf990d03a8b2cc11caa86e3981a9
parent01f8a361389e065aa671ef17703a8d007100a881 (diff)
downloadevolution-data-server-994a77156da4eead849887e7699c8bcff580c8ba.tar.gz
Avoid possible deadlock with CamelStoreSummary locks
Recently added store_summary_sync_folder_summary_count_cb() could cause deadlock when locking SUMMARY_LOCK first, and then calling functions which lock REF_LOCK before SUMMARY_LOCK. Locking REF_LOCK first avoids this.
-rw-r--r--camel/camel-store-summary.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c
index 96d913240..1b3c7e84b 100644
--- a/camel/camel-store-summary.c
+++ b/camel/camel-store-summary.c
@@ -1115,10 +1115,12 @@ store_summary_sync_folder_summary_count_cb (CamelFolderSummary *folder_summary,
path = g_hash_table_lookup (summary->priv->folder_summaries, folder_summary);
g_return_if_fail (path != NULL);
+ camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
si = camel_store_summary_path (summary, path);
if (!si) {
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path);
return;
}
@@ -1136,6 +1138,7 @@ store_summary_sync_folder_summary_count_cb (CamelFolderSummary *folder_summary,
camel_store_summary_info_free (summary, si);
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
}
/**
@@ -1167,11 +1170,13 @@ camel_store_summary_connect_folder_summary (CamelStoreSummary *summary,
g_return_val_if_fail (path != NULL, FALSE);
g_return_val_if_fail (folder_summary != NULL, FALSE);
+ camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
si = camel_store_summary_path (summary, path);
if (!si) {
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path);
return FALSE;
}
@@ -1180,6 +1185,7 @@ camel_store_summary_connect_folder_summary (CamelStoreSummary *summary,
if (g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) {
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
g_warning ("%s: Store summary %p already listens on folder summary %p", G_STRFUNC, summary, folder_summary);
return FALSE;
}
@@ -1189,6 +1195,7 @@ camel_store_summary_connect_folder_summary (CamelStoreSummary *summary,
g_signal_connect (folder_summary, "notify::unread-count", G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary);
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
return TRUE;
}
@@ -1214,10 +1221,12 @@ camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary,
g_return_val_if_fail (summary->priv != NULL, FALSE);
g_return_val_if_fail (folder_summary != NULL, FALSE);
+ camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
if (!g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) {
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
g_warning ("%s: Store summary %p is not connected to folder summary %p", G_STRFUNC, summary, folder_summary);
return FALSE;
}
@@ -1226,6 +1235,7 @@ camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary,
g_hash_table_remove (summary->priv->folder_summaries, folder_summary);
camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK);
+ camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_REF_LOCK);
return TRUE;
}