Patch: properly shutdown IMAP IDLE on getting disconnect



	Hi,

	This patch avoids a race condition on IDLE implementation.

	This is the schenario. If we're requesting IDLE to start from the IMAP
worker thread, we wait in a cond_wait, and the idle thread runs a code
"idle_real_start" that does the connection startup, and this is ok.

	But, if in the middle of this idle_real_start, we lose the connection
with server, we run the IDLE shutdown code, that gets the idle_lock. And
this idle_lock is retained by the IMAP worker while condwait does not
return. So deathlock.

	What we do is checking if we're in the idle thread without idle lock
(this means we are in the idle_real_start, so we cannot get the
idle_lock, and we should simply silently finish the connection).

Changelog entry:

* libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c:
  on disconnecting from network, avoid any network communication if we're
  in idle loop and we don't have the idle lock. This avoids some crashes
  on starting idle if connection is shutdown.


-- 
José Dapena Paz <jdapena igalia com>
Igalia
diff --git a/ChangeLog b/ChangeLog
index e521ef2..d7e38af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-07-10  Jose Dapena Paz  <jdapena igalia com>
+
+	* libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c:
+	on disconnecting from network, avoid any network communication if we're
+	in idle loop and we don't have the idle lock. This avoids some crashes
+	on starting idle if connection is shutdown.
+
 2009-07-03  Sergio Villar Senin  <svillar igalia com>
 
 	* libtinymailui-gtk/tny-gtk-header-list-model.c
diff --git a/docs/devel/reference/xml/.svnignore b/docs/devel/reference/xml/.svnignore
deleted file mode 100644
index 72e8ffc..0000000
--- a/docs/devel/reference/xml/.svnignore
+++ /dev/null
@@ -1 +0,0 @@
-*
diff --git a/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c b/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
index 6c0a99a..082cb8d 100644
--- a/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
+++ b/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
@@ -2402,10 +2402,19 @@ imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *
 
 	imap_debug ("imap_disconnect_offline\n");
 
-	let_idle_die (store, TRUE);
-	CAMEL_SERVICE_REC_LOCK (service, connect_lock);
-	camel_imap_store_stop_idle (store);
-	CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
+	if (store->in_idle && store->idle_thread && store->idle_thread == g_thread_self ()) {
+		if (store->idle_prefix) {
+			g_free (store->idle_prefix);
+			store->idle_prefix = NULL;
+		}
+		store->idle_kill  = TRUE;
+		store->idle_cont = FALSE;
+	} else {
+
+		CAMEL_SERVICE_REC_LOCK (service, connect_lock);
+		camel_imap_store_stop_idle (store);
+		CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
+	}
 
 	if (store->istream) {
 		camel_stream_close(store->istream);
@@ -2451,17 +2460,34 @@ imap_disconnect_online (CamelService *service, gboolean clean, CamelException *e
 {
 	CamelImapStore *store = CAMEL_IMAP_STORE (service);
 	CamelImapResponse *response;
+	gboolean do_disconnect = TRUE;
 
 	imap_debug ("imap_disconnect_online\n");
 
-	if (clean)
-		let_idle_die (store, TRUE);
+	if (!g_static_rec_mutex_trylock (store->idle_lock)) {
+		if (store->in_idle && store->idle_thread && store->idle_thread == g_thread_self ()) {
+			if (store->idle_prefix) {
+				g_free (store->idle_prefix);
+				store->idle_prefix = NULL;
+			}
+			store->idle_kill  = TRUE;
+			store->idle_cont = FALSE;
+			do_disconnect = FALSE;
+		}
+	} else {
+		g_static_rec_mutex_unlock (store->idle_lock);
+	}
+
+	if (do_disconnect) {
+		if (clean)
+			let_idle_die (store, TRUE);
 
-	camel_imap_store_stop_idle_connect_lock (store);
+		camel_imap_store_stop_idle_connect_lock (store);
 
-	if (store->connected && clean) {
-		response = camel_imap_command (store, NULL, NULL, "LOGOUT");
-		camel_imap_response_free (store, response);
+		if (store->connected && clean) {
+			response = camel_imap_command (store, NULL, NULL, "LOGOUT");
+			camel_imap_response_free (store, response);
+		}
 	}
 
 	imap_disconnect_offline (service, clean, ex);
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
index 7c26df4..15d6a20 100644
--- a/po/Makefile.in.in
+++ b/po/Makefile.in.in
@@ -16,7 +16,7 @@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
 PACKAGE = @PACKAGE@
 VERSION = @VERSION@
 
-SHELL = /bin/sh
+SHELL = @SHELL@
 @SET_MAKE@
 
 srcdir = @srcdir@
@@ -56,7 +56,7 @@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
 SOURCES = 
 POFILES = @POFILES@
 GMOFILES = @GMOFILES@
-DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \
+DISTFILES = LINGUAS ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \
 $(POFILES) $(GMOFILES) $(SOURCES)
 
 POTFILES = \
@@ -263,8 +263,7 @@ POTFILES: POTFILES.in
 
 Makefile: Makefile.in.in ../config.status POTFILES
 	cd .. \
-	  && CONFIG_FILES=$(subdir)/$  in CONFIG_HEADERS= \
-	       $(SHELL) ./config.status
+	  && $(SHELL) ./config.status $(subdir)/$  in
 
 # Tell versions [3.59,3.63) of GNU make not to export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.


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