]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imapc: Avoid assert-crashing when replacing mail stream with a new one.
authorTimo Sirainen <tss@iki.fi>
Wed, 14 Dec 2011 11:00:05 +0000 (13:00 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 14 Dec 2011 11:00:05 +0000 (13:00 +0200)
src/lib-storage/index/imapc/imapc-mail-fetch.c
src/lib-storage/index/index-mail.c

index 1d2ff1c1cd338b0780851655bad01538bc8087b4..3d8c66845071faa47ef81db188266906e779ba00 100644 (file)
@@ -277,13 +277,13 @@ void imapc_mail_init_stream(struct imapc_mail *mail, bool have_body)
        if (imail->mail.v.istream_opened != NULL) {
                if (imail->mail.v.istream_opened(_mail,
                                                 &imail->data.stream) < 0) {
-                       i_stream_unref(&imail->data.stream);
+                       index_mail_close_streams(imail);
                        return;
                }
        } else if (have_body) {
                ret = i_stream_get_size(imail->data.stream, TRUE, &size);
                if (ret < 0) {
-                       i_stream_unref(&imail->data.stream);
+                       index_mail_close_streams(imail);
                        return;
                }
                i_assert(ret != 0);
@@ -295,7 +295,7 @@ void imapc_mail_init_stream(struct imapc_mail *mail, bool have_body)
 
        imail->data.stream_has_only_header = !have_body;
        if (index_mail_init_stream(imail, NULL, NULL, &input) < 0)
-               i_stream_unref(&imail->data.stream);
+               index_mail_close_streams(imail);
 }
 
 static void
@@ -311,7 +311,7 @@ imapc_fetch_stream(struct imapc_mail *mail,
                if (!body)
                        return;
                /* maybe the existing stream has no body. replace it. */
-               i_stream_unref(&imail->data.stream);
+               index_mail_close_streams(imail);
                if (mail->fd != -1) {
                        if (close(mail->fd) < 0)
                                i_error("close(imapc mail) failed: %m");
index 4d0c670348d21df3cbf1c8a8994bbc510f6aa666..85aef6f0494a47c144db97444f5e0e7d6bf02c0c 100644 (file)
@@ -1137,7 +1137,7 @@ void index_mail_init(struct index_mail *mail,
        }
 }
 
-void index_mail_close_streams(struct index_mail *mail)
+static void index_mail_close_streams_full(struct index_mail *mail, bool closing)
 {
        struct index_mail_data *data = &mail->data;
        struct message_part *parts;
@@ -1152,14 +1152,31 @@ void index_mail_close_streams(struct index_mail *mail)
                i_stream_unref(&data->filter_stream);
        if (data->stream != NULL) {
                data->destroying_stream = TRUE;
+               if (!closing) {
+                       /* we're replacing the stream with a new one. it's
+                          allowed to have references until the mail is closed
+                          (but we can't really check that) */
+                       i_stream_unset_destroy_callback(data->stream);
+               }
                i_stream_unref(&data->stream);
-               i_assert(!data->destroying_stream);
+               if (closing) {
+                       /* there must be no references to the mail when the
+                          mail is being closed. */
+                       i_assert(!mail->data.destroying_stream);
+               } else {
+                       data->destroying_stream = FALSE;
+               }
 
                data->initialized_wrapper_stream = FALSE;
                data->destroy_callback_set = FALSE;
        }
 }
 
+void index_mail_close_streams(struct index_mail *mail)
+{
+       index_mail_close_streams_full(mail, FALSE);
+}
+
 void index_mail_close(struct mail *_mail)
 {
        struct index_mail *mail = (struct index_mail *)_mail;
@@ -1174,7 +1191,8 @@ void index_mail_close(struct mail *_mail)
                index_mail_cache_dates(mail);
        }
 
-       index_mail_close_streams(mail);
+       index_mail_close_streams_full(mail, TRUE);
+
        if (mail->data.wanted_headers != NULL)
                mailbox_header_lookup_unref(&mail->data.wanted_headers);
 }