[evolution-data-server] Bug 750146 - [IMAPx] Deadlock when FETCH and STORE run at one time
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug 750146 - [IMAPx] Deadlock when FETCH and STORE run at one time
- Date: Mon, 1 Jun 2015 18:59:27 +0000 (UTC)
commit 8b05e84562303b6aec6d899eafb08fc55eec5949
Author: Milan Crha <mcrha redhat com>
Date: Mon Jun 1 20:58:03 2015 +0200
Bug 750146 - [IMAPx] Deadlock when FETCH and STORE run at one time
camel/providers/imapx/camel-imapx-job.c | 46 +++++++++++++++++++++++++++
camel/providers/imapx/camel-imapx-job.h | 3 ++
camel/providers/imapx/camel-imapx-mailbox.c | 30 ++++++++++++++---
camel/providers/imapx/camel-imapx-server.c | 10 +-----
4 files changed, 76 insertions(+), 13 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-job.c b/camel/providers/imapx/camel-imapx-job.c
index 7c79496..c470754 100644
--- a/camel/providers/imapx/camel-imapx-job.c
+++ b/camel/providers/imapx/camel-imapx-job.c
@@ -46,6 +46,8 @@ struct _CamelIMAPXRealJob {
CamelIMAPXMailbox *mailbox;
GMutex mailbox_lock;
+
+ CamelIMAPXMailbox *guard_mailbox_update; /* uses the mailbox_lock */
};
static void
@@ -124,6 +126,13 @@ camel_imapx_job_unref (CamelIMAPXJob *job)
if (real_job->destroy_data != NULL)
real_job->destroy_data (real_job->data);
+ g_mutex_lock (&real_job->mailbox_lock);
+ if (real_job->guard_mailbox_update) {
+ camel_imapx_mailbox_unlock_update (real_job->guard_mailbox_update);
+ g_clear_object (&real_job->guard_mailbox_update);
+ }
+ g_mutex_unlock (&real_job->mailbox_lock);
+
g_clear_object (&real_job->mailbox);
g_mutex_clear (&real_job->mailbox_lock);
@@ -232,6 +241,13 @@ camel_imapx_job_done (CamelIMAPXJob *job)
real_job = (CamelIMAPXRealJob *) job;
+ g_mutex_lock (&real_job->mailbox_lock);
+ if (real_job->guard_mailbox_update) {
+ camel_imapx_mailbox_unlock_update (real_job->guard_mailbox_update);
+ g_clear_object (&real_job->guard_mailbox_update);
+ }
+ g_mutex_unlock (&real_job->mailbox_lock);
+
g_mutex_lock (&real_job->done_mutex);
real_job->done_flag = TRUE;
g_cond_broadcast (&real_job->done_cond);
@@ -263,6 +279,36 @@ camel_imapx_job_run (CamelIMAPXJob *job,
return success;
}
+void
+camel_imapx_job_guard_mailbox_update (CamelIMAPXJob *job,
+ CamelIMAPXMailbox *mailbox)
+{
+ CamelIMAPXRealJob *real_job;
+
+ g_return_if_fail (CAMEL_IS_IMAPX_JOB (job));
+
+ if (mailbox)
+ g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+ real_job = (CamelIMAPXRealJob *) job;
+
+ g_mutex_lock (&real_job->mailbox_lock);
+
+ if (mailbox != real_job->guard_mailbox_update) {
+ if (real_job->guard_mailbox_update) {
+ camel_imapx_mailbox_unlock_update (real_job->guard_mailbox_update);
+ g_clear_object (&real_job->guard_mailbox_update);
+ }
+
+ if (mailbox) {
+ real_job->guard_mailbox_update = g_object_ref (mailbox);
+ camel_imapx_mailbox_lock_update (real_job->guard_mailbox_update);
+ }
+ }
+
+ g_mutex_unlock (&real_job->mailbox_lock);
+}
+
gboolean
camel_imapx_job_matches (CamelIMAPXJob *job,
CamelIMAPXMailbox *mailbox,
diff --git a/camel/providers/imapx/camel-imapx-job.h b/camel/providers/imapx/camel-imapx-job.h
index b234880..cf09fc3 100644
--- a/camel/providers/imapx/camel-imapx-job.h
+++ b/camel/providers/imapx/camel-imapx-job.h
@@ -64,6 +64,9 @@ void camel_imapx_job_done (CamelIMAPXJob *job);
gboolean camel_imapx_job_run (CamelIMAPXJob *job,
CamelIMAPXServer *is,
GError **error);
+void camel_imapx_job_guard_mailbox_update
+ (CamelIMAPXJob *job,
+ CamelIMAPXMailbox *mailbox);
gboolean camel_imapx_job_matches (CamelIMAPXJob *job,
CamelIMAPXMailbox *mailbox,
const gchar *uid);
diff --git a/camel/providers/imapx/camel-imapx-mailbox.c b/camel/providers/imapx/camel-imapx-mailbox.c
index 62c0b51..5e576e4 100644
--- a/camel/providers/imapx/camel-imapx-mailbox.c
+++ b/camel/providers/imapx/camel-imapx-mailbox.c
@@ -51,7 +51,9 @@ struct _CamelIMAPXMailboxPrivate {
CamelIMAPXMailboxState state;
GMutex property_lock;
- GRecMutex update_lock;
+ GMutex update_lock;
+ GCond update_cond;
+ gboolean update_is_locked;
/* Protected by the "property_lock". */
GHashTable *attributes;
@@ -98,7 +100,8 @@ imapx_mailbox_finalize (GObject *object)
g_free (priv->name);
g_mutex_clear (&priv->property_lock);
- g_rec_mutex_clear (&priv->update_lock);
+ g_mutex_clear (&priv->update_lock);
+ g_cond_clear (&priv->update_cond);
g_hash_table_destroy (priv->attributes);
g_sequence_free (priv->message_map);
g_strfreev (priv->quota_roots);
@@ -125,7 +128,9 @@ camel_imapx_mailbox_init (CamelIMAPXMailbox *mailbox)
mailbox->priv = CAMEL_IMAPX_MAILBOX_GET_PRIVATE (mailbox);
g_mutex_init (&mailbox->priv->property_lock);
- g_rec_mutex_init (&mailbox->priv->update_lock);
+ g_mutex_init (&mailbox->priv->update_lock);
+ g_cond_init (&mailbox->priv->update_cond);
+ mailbox->priv->update_is_locked = FALSE;
mailbox->priv->message_map = g_sequence_new (NULL);
mailbox->priv->permanentflags = ~0;
mailbox->priv->state = CAMEL_IMAPX_MAILBOX_STATE_CREATED;
@@ -1198,7 +1203,15 @@ camel_imapx_mailbox_lock_update (CamelIMAPXMailbox *mailbox)
{
g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
- g_rec_mutex_lock (&mailbox->priv->update_lock);
+ g_mutex_lock (&mailbox->priv->update_lock);
+
+ while (mailbox->priv->update_is_locked) {
+ g_cond_wait (&mailbox->priv->update_cond, &mailbox->priv->update_lock);
+ }
+
+ mailbox->priv->update_is_locked = TRUE;
+
+ g_mutex_unlock (&mailbox->priv->update_lock);
}
/* Prevents running FETCH and STORE at the same time for the given mailbox */
@@ -1207,5 +1220,12 @@ camel_imapx_mailbox_unlock_update (CamelIMAPXMailbox *mailbox)
{
g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
- g_rec_mutex_unlock (&mailbox->priv->update_lock);
+ g_mutex_lock (&mailbox->priv->update_lock);
+
+ if (mailbox->priv->update_is_locked) {
+ mailbox->priv->update_is_locked = FALSE;
+ g_cond_signal (&mailbox->priv->update_cond);
+ }
+
+ g_mutex_unlock (&mailbox->priv->update_lock);
}
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 565a642..6a1e4f7 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -8930,7 +8930,7 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
if (registered)
- camel_imapx_mailbox_lock_update (mailbox);
+ camel_imapx_job_guard_mailbox_update (job, mailbox);
if (registered && camel_imapx_job_run (job, is, error)) {
changes = data->changes;
@@ -8939,9 +8939,6 @@ camel_imapx_server_refresh_info (CamelIMAPXServer *is,
imapx_unregister_job (is, job);
}
- if (registered)
- camel_imapx_mailbox_unlock_update (mailbox);
-
camel_imapx_job_unref (job);
return changes;
@@ -9270,16 +9267,13 @@ imapx_server_sync_changes (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
if (job_type == IMAPX_JOB_SYNC_CHANGES && registered)
- camel_imapx_mailbox_lock_update (mailbox);
+ camel_imapx_job_guard_mailbox_update (job, mailbox);
success = registered && camel_imapx_job_run (job, is, error);
if (!success && registered)
imapx_unregister_job (is, job);
- if (job_type == IMAPX_JOB_SYNC_CHANGES && registered)
- camel_imapx_mailbox_unlock_update (mailbox);
-
camel_imapx_job_unref (job);
g_object_unref (folder);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]