diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-25 18:09:09 +0100 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-28 14:04:51 +0100 |
commit | 13557c29ce41064a2850bb3f1e0d3c84a23d79d8 (patch) | |
tree | 18ca91b95f3a2434168517efa5f6f519ad2630fd | |
parent | 7542842bcaf47323d519a1ec49b818315baf2dcd (diff) | |
download | evolution-data-server-13557c29ce41064a2850bb3f1e0d3c84a23d79d8.tar.gz |
Fix idle thread exit and locking
If we trigger its exit and wait for it while still holding the lock, it may
deadlock on the same lock. Also fix a multiple-unlock bug.
(cherry picked from commit ab8442ff77654a54cd6556bc73533bc386408c60)
-rw-r--r-- | camel/providers/imapx/camel-imapx-server.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c index 7b1c8159f..01449fc94 100644 --- a/camel/providers/imapx/camel-imapx-server.c +++ b/camel/providers/imapx/camel-imapx-server.c @@ -2054,16 +2054,19 @@ imapx_idle_thread (gpointer data) while (TRUE) { CamelIMAPXFolder *ifolder; + e_flag_clear (is->idle->idle_start_watch); IDLE_LOCK(is->idle); while ((ifolder = (CamelIMAPXFolder *) is->select_folder) && - is->idle->state == IMAPX_IDLE_PENDING) { + is->idle->state == IMAPX_IDLE_PENDING && + !is->idle->idle_exit) { time_t dwelled = time(NULL) - is->idle->started; if (dwelled < IMAPX_IDLE_DWELL_TIME) { IDLE_UNLOCK(is->idle); g_usleep((IMAPX_IDLE_DWELL_TIME - dwelled) * G_USEC_PER_SEC); + IDLE_LOCK(is->idle); continue; } IDLE_UNLOCK(is->idle); @@ -2078,6 +2081,7 @@ imapx_idle_thread (gpointer data) /* No way to asyncronously notify UI ? */ camel_exception_clear (ex); } + IDLE_LOCK(is->idle); } IDLE_UNLOCK(is->idle); @@ -2136,6 +2140,7 @@ static void imapx_exit_idle (CamelIMAPXServer *is) { CamelIMAPXIdle *idle = is->idle; + GThread *thread = NULL; if (!idle) return; @@ -2146,13 +2151,16 @@ imapx_exit_idle (CamelIMAPXServer *is) idle->idle_exit = TRUE; e_flag_set (idle->idle_start_watch); - if (idle->idle_thread) - g_thread_join (idle->idle_thread); + thread = idle->idle_thread; + idle->idle_thread = 0; } idle->idle_thread = NULL; IDLE_UNLOCK (idle); + if (thread) + g_thread_join (thread); + g_mutex_free (idle->idle_lock); if (idle->idle_start_watch) e_flag_free (idle->idle_start_watch); |