Patch: add weak references to current_folder, old_folder and last_folder in imap store



	Hi,

	This patch adds weak references to current_folder, old_folder and
last_folder in imap store, to make them be removed when the objects are
finalized. This should prevent some crashes and memory corruptions
caused by accessing these folders after they're freed.

	The patch does not include Changelog entry. It would be:

* libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.[ch]:
	* Now references to current_folder, old_folder and last_folder
	  are weak references. This way, when they're finalized we
	  properly remove the store reference to them.
	* Removed some small leaks and compilation warnings.
* libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c,
  libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c:
	* Use weak references to folders in accesses to store.
-- 
José Dapena Paz <jdapena igalia com>
Igalia
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c	(revision 3640)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c	(working copy)
@@ -321,6 +321,7 @@
 			camel_imap_folder_selected (folder, response2, &nex, TRUE);
 			camel_imap_response_free (imap_store, response2);
 		}
+		camel_exception_clear (&nex);
 		camel_imap_store_start_idle (imap_store);
 	}
 
@@ -395,6 +396,18 @@
 
 	let_idle_die (imap_store, TRUE);
 
+	if (imap_store->current_folder) {
+		camel_object_unhook_event (imap_store->current_folder, "finalize",
+					   current_folder_finalize, imap_store);
+		imap_store->current_folder = NULL;
+	}
+
+	if (imap_store->old_folder) {
+		camel_object_unhook_event (imap_store->old_folder, "finalize",
+					   old_folder_finalize, imap_store);
+		imap_store->old_folder = NULL;
+	}
+
 	/* This frees current_folder, folders, authtypes, streams, and namespace. */
 	camel_service_disconnect((CamelService *)imap_store, TRUE, NULL);
 
@@ -901,7 +914,7 @@
 	CamelImapResponse *response;
 	CamelStream *tcp_stream;
 	CamelSockOptData sockopt;
-	gboolean force_imap4 = FALSE, ssl_ena = FALSE;
+	gboolean force_imap4 = FALSE;
 	gboolean clean_quit = TRUE;
 	char *buf;
 	gboolean not_ssl = TRUE;
@@ -2121,6 +2134,12 @@
 	/* if (store->current_folder && CAMEL_IS_OBJECT (store->current_folder))
 		camel_object_unref (store->current_folder); */
 	store->old_folder = store->current_folder;
+	if (store->old_folder)
+		camel_object_hook_event (store->old_folder, "finalize",
+					 old_folder_finalize, store);
+	if (store->current_folder)
+		camel_object_unhook_event (store->current_folder, "finalize",
+					   current_folder_finalize, store);
 	store->current_folder = NULL;
 
 	if (store->authtypes) {
@@ -2629,6 +2648,8 @@
 
 	if (imap_store->current_folder) {
 		/* camel_object_unref (imap_store->current_folder); */
+		camel_object_unhook_event (imap_store->current_folder, "finalize",
+					   current_folder_finalize, imap_store);
 		imap_store->current_folder = NULL;
 	}
 
@@ -2806,6 +2827,8 @@
 		CamelException local_ex;
 
 		imap_store->current_folder = new_folder;
+		camel_object_hook_event (imap_store, "finalize",
+					 current_folder_finalize, imap_store);
 		/* camel_object_ref (new_folder); */
 		camel_exception_init (&local_ex);
 		//camel_imap_folder_selected (new_folder, response, &local_ex, TRUE);
@@ -2813,6 +2836,8 @@
 		if (camel_exception_is_set (&local_ex)) {
 			camel_exception_xfer (ex, &local_ex);
 			/* camel_object_unref (imap_store->current_folder); */
+			camel_object_unhook_event (imap_store, "finalize",
+						   current_folder_finalize, imap_store);
 			imap_store->current_folder = NULL;
 			camel_object_unref (new_folder);
 			new_folder = NULL;
@@ -2881,6 +2906,8 @@
 		camel_object_unref (imap_store->current_folder);*/
 
 	/* no need to actually create a CamelFolder for INBOX */
+	camel_object_unhook_event (imap_store->current_folder, "finalize",
+				   current_folder_finalize, imap_store);
 	imap_store->current_folder = NULL;
 
 	response = camel_imap_command(imap_store, NULL, ex, "DELETE %F", folder_name);
@@ -3046,7 +3073,7 @@
 
 		g_mkdir (newpath, S_IRWXU);
 
-		while (file = g_dir_read_name (dir)) {
+		while ((file = g_dir_read_name (dir)) != NULL) {
 			gchar *old_fullname;
 			gchar *new_fullname;
 			old_fullname = g_strdup_printf ("%s/%s", oldpath, file);
@@ -3105,6 +3132,8 @@
 	/*if (imap_store->current_folder)
 		camel_object_unref (imap_store->current_folder); */
 	/* no need to actually create a CamelFolder for INBOX */
+	camel_object_unhook_event (imap_store->current_folder, "finalize",
+				   current_folder_finalize, imap_store);
 	imap_store->current_folder = NULL;
 
 	/* Undefined progress */
@@ -4454,3 +4483,26 @@
 
 	return nread;
 }
+
+void 
+current_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data)
+{
+	CamelImapStore *store = (CamelImapStore *) user_data;
+
+	store->current_folder = NULL;
+}
+void 
+old_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data)
+{
+	CamelImapStore *store = (CamelImapStore *) user_data;
+
+	store->old_folder = NULL;
+}
+
+void 
+last_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data)
+{
+	CamelImapStore *store = (CamelImapStore *) user_data;
+
+	store->last_folder = NULL;
+}
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h	(revision 3640)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h	(working copy)
@@ -200,6 +200,10 @@
 void camel_imap_store_start_idle (CamelImapStore *store);
 void camel_imap_recon (CamelImapStore *store, CamelException *mex, gboolean was_cancel);
 
+void current_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data);
+void old_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data);
+void last_folder_finalize (CamelObject *stream, gpointer event_data, gpointer user_data);
+
 G_END_DECLS
 
 #endif /* CAMEL_IMAP_STORE_H */
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c	(revision 3640)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c	(working copy)
@@ -798,8 +798,11 @@
 		imap_folder->idle_lock = NULL;
 	}
 
-	if (store->current_folder == (CamelFolder*) object)
+	if (store->current_folder == (CamelFolder*) object) {
+		camel_object_unhook_event (store->current_folder, "finalize",
+					   current_folder_finalize, store);
 		store->current_folder = NULL;
+	}
 
 	if (imap_folder->search)
 		camel_object_unref (CAMEL_OBJECT (imap_folder->search));
@@ -3826,6 +3829,7 @@
 		if (tbreak)
 			break;
 	}
+	camel_exception_clear (&ex);
 	if (resp)
 		g_free (resp);
 errh:
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c	(revision 3640)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c	(working copy)
@@ -135,15 +135,27 @@
 		if (store->current_folder && CAMEL_IS_OBJECT (store->current_folder))
 			camel_object_unref(store->current_folder); */
 
-		if (!folder)
+		if (!folder) {
 			store->last_folder = store->current_folder;
-		else {
+			if (store->last_folder)
+				camel_object_hook_event (store->last_folder, "finalize",
+							 last_folder_finalize, store);
+		} else {
 			modseq = camel_imap_folder_get_highestmodseq (CAMEL_IMAP_FOLDER (folder));
+			if (store->last_folder)
+				camel_object_unhook_event (store->last_folder, "finalize",
+							   last_folder_finalize, store);
 			store->last_folder = NULL;
 		}
-
+		
+		if (store->current_folder)
+			camel_object_unhook_event (store->current_folder, "finalize",
+						   current_folder_finalize, store);
 		store->current_folder = folder;
-
+		if (store->current_folder)
+			camel_object_hook_event (store->current_folder, "finalize",
+						 current_folder_finalize, store);
+		
 		if (modseq && (store->capabilities & IMAP_CAPABILITY_QRESYNC))
 		{
 			CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary);
@@ -285,11 +297,19 @@
 		gboolean wasnull = FALSE;
 		if (!store->current_folder) {
 			store->current_folder = store->last_folder;
+			if (store->current_folder)
+				camel_object_hook_event (store->current_folder, "finalize",
+							 current_folder_finalize, store);
 			wasnull = TRUE;
 		}
 		camel_imap_store_stop_idle (store);
-		if (wasnull)
-			store->current_folder = NULL;
+		if (wasnull) {
+			if (store->current_folder) {
+				camel_object_unhook_event (store->current_folder, "finalize",
+							   current_folder_finalize, store);
+				store->current_folder = NULL;
+			}
+		}
 	}
 
 	/* Check for current folder */
@@ -1283,9 +1303,9 @@
 
 		start = *p ? p + 1 : p;
 	}
-
+	
 	g_ptr_array_free (args, TRUE);
-
+	
 	return out;
 }
 
@@ -1294,10 +1314,10 @@
 {
 	va_list ap;
 	char *result;
-
+	
 	va_start (ap, fmt);
 	result = imap_command_strdup_vprintf (store, fmt, ap);
 	va_end (ap);
-
+	
 	return result;
 }


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