]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-fs: Assert-crash if file's istream isn't closed at fs_file_close()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 21 Apr 2016 14:59:19 +0000 (17:59 +0300)
committerGitLab <gitlab@git.dovecot.net>
Fri, 22 Apr 2016 22:41:53 +0000 (01:41 +0300)
Some backends can't guarantee that the istream stays usable after the file
is closed.

src/lib-fs/fs-api-private.h
src/lib-fs/fs-api.c

index 6f931c19c29db5518f9444bf107cccc49b4642e1..d471dc46f68124046e365f55355e0808d46dfd17 100644 (file)
@@ -120,6 +120,7 @@ struct fs_file {
        unsigned int read_or_prefetch_counted:1;
        unsigned int lookup_metadata_counted:1;
        unsigned int stat_counted:1;
+       unsigned int istream_open:1;
 };
 
 struct fs_lock {
index b50fbe0f53ce6c3f69dcae686f7fe41528e2f613..aa5002ced1823617fce4d5765701d7811fec60a1 100644 (file)
@@ -275,6 +275,11 @@ void fs_file_close(struct fs_file *file)
        if (file->fs->v.file_close != NULL) T_BEGIN {
                file->fs->v.file_close(file);
        } T_END;
+
+       /* check this only after closing, because some of the fs backends keep
+          the istream internally open and don't call the destroy-callback
+          until after file_close() */
+       i_assert(!file->istream_open);
 }
 
 enum fs_properties fs_get_properties(struct fs *fs)
@@ -494,6 +499,13 @@ ssize_t fs_read(struct fs_file *file, void *buf, size_t size)
        return fs_read_via_stream(file, buf, size);
 }
 
+static void fs_file_istream_destroyed(struct fs_file *file)
+{
+       i_assert(file->istream_open);
+
+       file->istream_open = FALSE;
+}
+
 struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
 {
        struct istream *input, *inputs[2];
@@ -513,6 +525,7 @@ struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
                i_stream_ref(file->seekable_input);
                return file->seekable_input;
        }
+       i_assert(!file->istream_open);
        T_BEGIN {
                input = file->fs->v.read_stream(file, max_buffer_size);
        } T_END;
@@ -559,6 +572,8 @@ struct istream *fs_read_stream(struct fs_file *file, size_t max_buffer_size)
                }
                i_stream_seek(input, 0);
        }
+       file->istream_open = TRUE;
+       i_stream_add_destroy_callback(input, fs_file_istream_destroyed, file);
        return input;
 }