]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
mdbox: Don't crash when trying to rebuild storage at deinit.
authorTimo Sirainen <tss@iki.fi>
Sat, 6 Mar 2010 10:52:59 +0000 (12:52 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 6 Mar 2010 10:52:59 +0000 (12:52 +0200)
--HG--
branch : HEAD

src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-storage.c

index 20721ac990481e29fbad34874ba9ca5b6eefdbb3..ee8488344a74fa927f7717401cad0de1666f092c 100644 (file)
@@ -723,6 +723,8 @@ static void rebuild_update_refcounts(struct mdbox_storage_rebuild_context *ctx)
 
 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);
index e5509b9bc4e73c49440dd708096bf939852cd86c..381b58b120b92c29c3d11c603e0f4a8d5d922c34 100644 (file)
@@ -340,14 +340,17 @@ struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user)
 
 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;
        }
 }
 
index 73bfc52206c8fbb1117c83b578a22b5b8a4e3484..7d99b9e5cc1aad90220a685f1e9b75c98eecb820 100644 (file)
@@ -324,16 +324,20 @@ void mail_storage_unref(struct mail_storage **_storage)
 
        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();