[evolution-data-server/gnome-2-30] Fix idle thread exit and locking



commit 13557c29ce41064a2850bb3f1e0d3c84a23d79d8
Author: David Woodhouse <David Woodhouse intel com>
Date:   Fri Jun 25 18:09:09 2010 +0100

    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)

 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 7b1c815..01449fc 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]