From 0ee52dafcc5b25c031e289d1d65ecccc859ebd3c Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Thu, 21 Apr 2016 17:59:19 +0300 Subject: [PATCH] lib-fs: Assert-crash if file's istream isn't closed at fs_file_close() Some backends can't guarantee that the istream stays usable after the file is closed. --- src/lib-fs/fs-api-private.h | 1 + src/lib-fs/fs-api.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/lib-fs/fs-api-private.h b/src/lib-fs/fs-api-private.h index 6f931c19c2..d471dc46f6 100644 --- a/src/lib-fs/fs-api-private.h +++ b/src/lib-fs/fs-api-private.h @@ -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 { diff --git a/src/lib-fs/fs-api.c b/src/lib-fs/fs-api.c index b50fbe0f53..aa5002ced1 100644 --- a/src/lib-fs/fs-api.c +++ b/src/lib-fs/fs-api.c @@ -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; }