changeset 10843:e3672e7c0f9f HEAD

mdbox: Don't crash when trying to rebuild storage at deinit.
author Timo Sirainen <tss@iki.fi>
date Sat, 06 Mar 2010 12:52:59 +0200
parents a81aceb9f55b
children 3bfb1e9f556b
files src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c src/lib-storage/mail-namespace.c src/lib-storage/mail-storage.c
diffstat 3 files changed, 17 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c	Sat Mar 06 12:30:53 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c	Sat Mar 06 12:52:59 2010 +0200
@@ -723,6 +723,8 @@
 
 static int rebuild_finish(struct mdbox_storage_rebuild_context *ctx)
 {
+	i_assert(ctx->default_list != NULL);
+
 	if (rebuild_handle_zero_refs(ctx) < 0)
 		return -1;
 	rebuild_update_refcounts(ctx);
--- a/src/lib-storage/mail-namespace.c	Sat Mar 06 12:30:53 2010 +0200
+++ b/src/lib-storage/mail-namespace.c	Sat Mar 06 12:52:59 2010 +0200
@@ -340,14 +340,17 @@
 
 void mail_namespaces_deinit(struct mail_namespace **_namespaces)
 {
-	struct mail_namespace *ns, *namespaces = *_namespaces;
+	struct mail_namespace *ns, *next;
 
-	*_namespaces = NULL;
-	while (namespaces != NULL) {
-		ns = namespaces;
-		namespaces = namespaces->next;
+	/* update *_namespaces as needed, instead of immediately setting it
+	   to NULL. for example mdbox_storage.destroy() wants to go through
+	   user's namespaces. */
+	while (*_namespaces != NULL) {
+		ns = *_namespaces;
+		next = ns->next;
 
 		mail_namespace_free(ns);
+		*_namespaces = next;
 	}
 }
 
--- a/src/lib-storage/mail-storage.c	Sat Mar 06 12:30:53 2010 +0200
+++ b/src/lib-storage/mail-storage.c	Sat Mar 06 12:52:59 2010 +0200
@@ -324,16 +324,20 @@
 
 	i_assert(storage->refcount > 0);
 
-	*_storage = NULL;
-
-	if (--storage->refcount > 0)
+	/* set *_storage=NULL only after calling destroy() callback.
+	   for example mdbox wants to access ns->storage */
+	if (--storage->refcount > 0) {
+		*_storage = NULL;
 		return;
+	}
 
 	DLLIST_REMOVE(&storage->user->storages, storage);
 
 	if (storage->v.destroy != NULL)
 		storage->v.destroy(storage);
 	i_free(storage->error_string);
+
+	*_storage = NULL;
 	pool_unref(&storage->pool);
 
 	mail_index_alloc_cache_destroy_unrefed();