# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../dovecot/dovecot-2.2.1-0000-upstream-fixes.patch # Copyright (C) 2013 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END --- From a69bfa0e486d70db4ee6e7553bd7235d9707ff58 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 19 Apr 2013 14:29:23 +0300 Subject: [PATCH] Compiling fix for Sun compilers. I wish gcc/clang warned about these as well, as sometimes they indicate bugs. diff --git a/src/imap-urlauth/imap-urlauth-worker.c b/src/imap-urlauth/imap-urlauth-worker.c index ad02c81..6d94a8f 100644 --- a/src/imap-urlauth/imap-urlauth-worker.c +++ b/src/imap-urlauth/imap-urlauth-worker.c @@ -941,7 +941,7 @@ static void main_stdio_run(const char *access_user, { bool debug; - debug = getenv("DEBUG"); + debug = getenv("DEBUG") != NULL; access_user = access_user != NULL ? access_user : getenv("USER"); if (access_user == NULL && IS_STANDALONE()) access_user = getlogin(); diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index b89adcf..179507c 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -663,7 +663,7 @@ struct timeout *io_loop_move_timeout(struct timeout **_timeout) bool io_loop_have_ios(struct ioloop *ioloop) { - return ioloop->io_files; + return ioloop->io_files != NULL; } bool io_loop_have_immediate_timeouts(struct ioloop *ioloop) -- 1.7.10.2 From d70baed80e47be3a7587901278dc74811f0a4873 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 20 Apr 2013 20:58:06 +0300 Subject: [PATCH] stats plugin: Fixed memory leak. diff --git a/src/plugins/stats/stats-plugin.c b/src/plugins/stats/stats-plugin.c index 27dae5b..ee4e9af 100644 --- a/src/plugins/stats/stats-plugin.c +++ b/src/plugins/stats/stats-plugin.c @@ -388,6 +388,7 @@ static void stats_transaction_free(struct stats_user *suser, trans_stats_add(&suser->session_stats.trans_stats, &strans->trans->stats); + i_free(strans); } static int -- 1.7.10.2 From ce10df9f5cc0dc658ece187606f403a814872696 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 20 Apr 2013 21:02:30 +0300 Subject: [PATCH] Fixed a memory leak. diff --git a/src/lib-mail/istream-attachment-connector.c b/src/lib-mail/istream-attachment-connector.c index 4fa6ebf..0cbedb2 100644 --- a/src/lib-mail/istream-attachment-connector.c +++ b/src/lib-mail/istream-attachment-connector.c @@ -88,6 +88,20 @@ int istream_attachment_connector_add(struct istream_attachment_connector *conn, return 0; } +static void +istream_attachment_connector_free(struct istream_attachment_connector *conn) +{ + struct istream *const *streamp, *stream; + + array_foreach(&conn->streams, streamp) { + stream = *streamp; + if (stream != NULL) + i_stream_unref(&stream); + } + i_stream_unref(&conn->base_input); + pool_unref(&conn->pool); +} + struct istream * istream_attachment_connector_finish(struct istream_attachment_connector **_conn) { @@ -111,8 +125,7 @@ istream_attachment_connector_finish(struct istream_attachment_connector **_conn) inputs = array_idx_modifiable(&conn->streams, 0); input = i_stream_create_concat(inputs); - i_stream_unref(&conn->base_input); - pool_unref(&conn->pool); + istream_attachment_connector_free(conn); return input; } @@ -122,6 +135,5 @@ void istream_attachment_connector_abort(struct istream_attachment_connector **_c *_conn = NULL; - i_stream_unref(&conn->base_input); - pool_unref(&conn->pool); + istream_attachment_connector_free(conn); } -- 1.7.10.2 From eada33e3bff7e25a7b952ebb08244aba86754e92 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 20 Apr 2013 21:57:47 +0300 Subject: [PATCH] lib-storage: Avoid wasting data stack during searches. diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 0077115..9278b6d 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -1377,7 +1377,9 @@ static int search_match_next(struct index_search_context *ctx) } for (i = 0; i < n && ret < 0; i++) { ctx->cur_mail->lookup_abort = cache_lookups[i]; - ret = search_match_once(ctx); + T_BEGIN { + ret = search_match_once(ctx); + } T_END; } ctx->cur_mail->lookup_abort = MAIL_LOOKUP_ABORT_NEVER; search_match_finish(ctx, ret); @@ -1556,7 +1558,9 @@ static int search_more_with_prefetching(struct index_search_context *ctx, int ret = 0; while ((mail = index_search_get_mail(ctx)) != NULL) { - ret = search_more_with_mail(ctx, mail); + T_BEGIN { + ret = search_more_with_mail(ctx, mail); + } T_END; if (ret <= 0) break; @@ -1612,8 +1616,10 @@ static bool search_finish_prefetch(struct index_search_context *ctx, mail_search_args_result_deserialize(ctx->mail_ctx.args, imail->data.search_results->data, imail->data.search_results->used); - ret = search_match_once(ctx); - search_match_finish(ctx, ret); + T_BEGIN { + ret = search_match_once(ctx); + search_match_finish(ctx, ret); + } T_END; ctx->cur_mail = NULL; return ret > 0; } -- 1.7.10.2 From 7276e7875fca54d44fcccb7a371951ac9639d09b Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 22 Apr 2013 18:45:04 +0300 Subject: [PATCH] zlib: Keep the last read mail cached uncompressed in a temp file. This fixes performance problems with partial IMAP FETCH commands. diff --git a/src/plugins/zlib/zlib-plugin.c b/src/plugins/zlib/zlib-plugin.c index d54ea54..5076702 100644 --- a/src/plugins/zlib/zlib-plugin.c +++ b/src/plugins/zlib/zlib-plugin.c @@ -3,7 +3,9 @@ #include "lib.h" #include "array.h" #include "istream.h" +#include "istream-seekable.h" #include "ostream.h" +#include "str.h" #include "mail-user.h" #include "dbox-single/sdbox-storage.h" #include "dbox-multi/mdbox-storage.h" @@ -26,6 +28,7 @@ MODULE_CONTEXT(obj, zlib_user_module) #define MAX_INBUF_SIZE (1024*1024) +#define ZLIB_MAIL_CACHE_EXPIRE_MSECS (60*1000) struct zlib_transaction_context { union mailbox_transaction_module_context module_ctx; @@ -33,9 +36,19 @@ struct zlib_transaction_context { struct mail *tmp_mail; }; +struct zlib_mail_cache { + struct timeout *to; + struct mailbox *box; + uint32_t uid; + + struct istream *input; +}; + struct zlib_user { union mail_user_module_context module_ctx; + struct zlib_mail_cache cache; + const struct compression_handler *save_handler; unsigned int save_level; }; @@ -48,9 +61,58 @@ static MODULE_CONTEXT_DEFINE_INIT(zlib_storage_module, &mail_storage_module_register); static MODULE_CONTEXT_DEFINE_INIT(zlib_mail_module, &mail_module_register); +static void zlib_mail_cache_close(struct zlib_user *zuser) +{ + struct zlib_mail_cache *cache = &zuser->cache; + + if (cache->to != NULL) + timeout_remove(&cache->to); + if (cache->input != NULL) + i_stream_unref(&cache->input); + memset(cache, 0, sizeof(*cache)); +} + +static struct istream * +zlib_mail_cache_open(struct zlib_user *zuser, struct mail *mail, + struct istream *input) +{ + struct zlib_mail_cache *cache = &zuser->cache; + struct istream *inputs[2]; + string_t *temp_prefix = t_str_new(128); + + zlib_mail_cache_close(zuser); + + /* zlib istream is seekable, but very slow. create a seekable istream + which we can use to quickly seek around in the stream that's been + read so far. usually the partial IMAP FETCHes continue from where + the previous left off, so this isn't strictly necessary, but with + the way lib-imap-storage's CRLF-cache works it has to seek backwards + somewhat, which causes a zlib stream reset. And the CRLF-cache isn't + easy to fix.. */ + input->seekable = FALSE; + inputs[0] = input; + inputs[1] = NULL; + mail_user_set_get_temp_prefix(temp_prefix, mail->box->storage->user->set); + input = i_stream_create_seekable_path(inputs, + i_stream_get_max_buffer_size(inputs[0]), + str_c(temp_prefix)); + i_stream_unref(&inputs[0]); + + cache->to = timeout_add(ZLIB_MAIL_CACHE_EXPIRE_MSECS, + zlib_mail_cache_close, zuser); + cache->box = mail->box; + cache->uid = mail->uid; + cache->input = input; + + /* index-mail wants the stream to be destroyed at close, so create + a new stream instead of just increasing reference. */ + return i_stream_create_limit(cache->input, (uoff_t)-1); +} + static int zlib_istream_opened(struct mail *_mail, struct istream **stream) { struct zlib_user *zuser = ZLIB_USER_CONTEXT(_mail->box->storage->user); + struct zlib_mail_cache *cache = &zuser->cache; struct mail_private *mail = (struct mail_private *)_mail; union mail_module_context *zmail = ZLIB_MAIL_CONTEXT(mail); struct istream *input; @@ -63,6 +125,15 @@ static int zlib_istream_opened(struct mail *_mail, struct istream **stream) if (_mail->saving && zuser->save_handler == NULL) return zmail->super.istream_opened(_mail, stream); + if (cache->uid == _mail->uid && cache->box == _mail->box) { + /* use the cached stream. when doing partial reads it should + already be seeked into the wanted offset. */ + i_stream_unref(stream); + i_stream_seek(cache->input, 0); + *stream = i_stream_create_limit(cache->input, (uoff_t)-1); + return zmail->super.istream_opened(_mail, stream); + } + handler = compression_detect_handler(*stream); if (handler != NULL) { if (handler->create_istream == NULL) { @@ -75,6 +146,8 @@ static int zlib_istream_opened(struct mail *_mail, struct istream **stream) input = *stream; *stream = handler->create_istream(input, TRUE); i_stream_unref(&input); + + *stream = zlib_mail_cache_open(zuser, _mail, *stream); } return zmail->super.istream_opened(_mail, stream); } @@ -265,6 +338,16 @@ static int zlib_mailbox_open(struct mailbox *box) return zbox->super.open(box); } +static void zlib_mailbox_close(struct mailbox *box) +{ + union mailbox_module_context *zbox = ZLIB_CONTEXT(box); + struct zlib_user *zuser = ZLIB_USER_CONTEXT(box->storage->user); + + if (zuser->cache.box == box) + zlib_mail_cache_close(zuser); + zbox->super.close(box); +} + static void zlib_mailbox_allocated(struct mailbox *box) { struct mailbox_vfuncs *v = box->vlast; @@ -274,6 +357,7 @@ static void zlib_mailbox_allocated(struct mailbox *box) zbox->super = *v; box->vlast = &zbox->super; v->open = zlib_mailbox_open; + v->close = zlib_mailbox_close; MODULE_CONTEXT_SET_SELF(box, zlib_storage_module, zbox); @@ -283,12 +367,24 @@ static void zlib_mailbox_allocated(struct mailbox *box) zlib_permail_alloc_init(box, v); } +static void zlib_mail_user_deinit(struct mail_user *user) +{ + struct zlib_user *zuser = ZLIB_USER_CONTEXT(user); + + zlib_mail_cache_close(zuser); + zuser->module_ctx.super.deinit(user); +} + static void zlib_mail_user_created(struct mail_user *user) { + struct mail_user_vfuncs *v = user->vlast; struct zlib_user *zuser; const char *name; zuser = p_new(user->pool, struct zlib_user, 1); + zuser->module_ctx.super = *v; + user->vlast = &zuser->module_ctx.super; + v->deinit = zlib_mail_user_deinit; name = mail_user_plugin_getenv(user, "zlib_save"); if (name != NULL && *name != '\0') { -- 1.7.10.2 From f7c17f745db01d854f315ddcbc9955125b4161ef Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 22 Apr 2013 21:51:01 +0300 Subject: [PATCH] stats plugin: Use nonblocking open() for stats fifo. This fixes hangs in it. Alternative would be to use alarm(). diff --git a/src/plugins/stats/stats-connection.c b/src/plugins/stats/stats-connection.c index b98e864..da07e9b 100644 --- a/src/plugins/stats/stats-connection.c +++ b/src/plugins/stats/stats-connection.c @@ -23,7 +23,7 @@ static bool stats_connection_open(struct stats_connection *conn) if (conn->open_failed) return FALSE; - conn->fd = open(conn->path, O_WRONLY); + conn->fd = open(conn->path, O_WRONLY | O_NONBLOCK); if (conn->fd == -1) { i_error("stats: open(%s) failed: %m", conn->path); conn->open_failed = TRUE; -- 1.7.10.2 From 43afe64ef8b8d2af9576b9e5a60feb0ef62223f9 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 13:28:17 +0300 Subject: [PATCH] OpenBSD compile fix: include sys/socket.h when checking for struct sockpeercred. diff --git a/configure.ac b/configure.ac index f06095f..a67d511 100644 --- a/configure.ac +++ b/configure.ac @@ -433,7 +433,7 @@ AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize madvise \ walkcontext dirfd clearenv malloc_usable_size glob fallocate \ posix_fadvise getpeereid getpeerucred) -AC_CHECK_TYPES([struct sockpeercred]) +AC_CHECK_TYPES([struct sockpeercred],,,[#include ]) AC_SEARCH_LIBS(clock_gettime, rt, [ AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function) -- 1.7.10.2 From 4288a8d102d241c32c5d53609f9242cd13263077 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 13:33:12 +0300 Subject: [PATCH] master: Fixed warning log message. diff --git a/src/master/master-settings.c b/src/master/master-settings.c index 29edf86..45e56ac 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -417,7 +417,7 @@ master_settings_verify(void *_set, pool_t pool, const char **error_r) const struct service_settings *default_service; #else rlim_t fd_limit; - const char *max_client_limit_source = "default_client_count"; + const char *max_client_limit_source = "default_client_limit"; unsigned int max_client_limit = set->default_client_limit; #endif -- 1.7.10.2 From 212c975ce882bcaebd49ff7d7ea8e1f109a25101 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 13:47:46 +0300 Subject: [PATCH] fts-solr: Don't crash if fts_solr setting is invalid. diff --git a/src/plugins/fts-solr/fts-backend-solr-old.c b/src/plugins/fts-solr/fts-backend-solr-old.c index 9fd8094..1845849 100644 --- a/src/plugins/fts-solr/fts-backend-solr-old.c +++ b/src/plugins/fts-solr/fts-backend-solr-old.c @@ -229,11 +229,14 @@ fts_backend_solr_init(struct fts_backend *_backend, const char **error_r) { struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend; struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user); - const struct fts_solr_settings *set = &fuser->set; const char *str; + if (fuser == NULL) { + *error_r = "Invalid fts_solr setting"; + return -1; + } if (solr_conn == NULL) { - if (solr_connection_init(set->url, set->debug, + if (solr_connection_init(fuser->set.url, fuser->set.debug, &solr_conn, error_r) < 0) return -1; } diff --git a/src/plugins/fts-solr/fts-backend-solr.c b/src/plugins/fts-solr/fts-backend-solr.c index f7b335f..8af1707 100644 --- a/src/plugins/fts-solr/fts-backend-solr.c +++ b/src/plugins/fts-solr/fts-backend-solr.c @@ -158,10 +158,13 @@ static int fts_backend_solr_init(struct fts_backend *_backend, const char **error_r) { struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user); - const struct fts_solr_settings *set = &fuser->set; + if (fuser == NULL) { + *error_r = "Invalid fts_solr setting"; + return -1; + } if (solr_conn == NULL) { - if (solr_connection_init(set->url, set->debug, + if (solr_connection_init(fuser->set.url, fuser->set.debug, &solr_conn, error_r) < 0) return -1; } -- 1.7.10.2 From efe39df75481a8c4579b70f24987eea075d0eeb8 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 16:20:48 +0300 Subject: [PATCH] lib-http: Makefile fix diff --git a/src/lib-http/Makefile.am b/src/lib-http/Makefile.am index 5c19c58..4127a14 100644 --- a/src/lib-http/Makefile.am +++ b/src/lib-http/Makefile.am @@ -50,7 +50,7 @@ test_libs = \ $(MODULE_LIBS) test_deps = \ - $(noinst_LTLIBRARIES) + $(noinst_LTLIBRARIES) \ ../lib-test/libtest.la \ ../lib/liblib.la -- 1.7.10.2 From 7c55c5055f78c849716efce14072a652157f3200 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 17:21:46 +0300 Subject: [PATCH] istream-seekable: Don't crash when seeking forwards past the data we haven't read yet. diff --git a/src/lib/istream-seekable.c b/src/lib/istream-seekable.c index a9c5d81..cf59138 100644 --- a/src/lib/istream-seekable.c +++ b/src/lib/istream-seekable.c @@ -345,6 +345,20 @@ i_stream_seekable_stat(struct istream_private *stream, bool exact) return 0; } +static void i_stream_seekable_seek(struct istream_private *stream, + uoff_t v_offset, bool mark) +{ + if (v_offset <= stream->istream.v_offset) { + /* seeking backwards */ + stream->istream.v_offset = v_offset; + stream->skip = stream->pos = 0; + } else { + /* we can't skip over data we haven't yet read and written to + our buffer/temp file */ + i_stream_default_seek_nonseekable(stream, v_offset, mark); + } +} + struct istream * i_streams_merge(struct istream *input[], size_t max_buffer_size, int (*fd_callback)(const char **path_r, void *context), @@ -388,6 +402,7 @@ i_streams_merge(struct istream *input[], size_t max_buffer_size, sstream->istream.read = i_stream_seekable_read; sstream->istream.stat = i_stream_seekable_stat; + sstream->istream.seek = i_stream_seekable_seek; sstream->istream.istream.readable_fd = FALSE; sstream->istream.istream.blocking = blocking; -- 1.7.10.2 From bd6b8ffcd0aef00aaa5b640d8e425fdcd0075993 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 20:51:34 +0300 Subject: [PATCH] dbox: Close file's fd only after its istream is destroyed. For example zlib plugin keeps the stream open as a cache even after the dbox_file has been destroyed. diff --git a/src/lib-storage/index/dbox-common/dbox-file.c b/src/lib-storage/index/dbox-common/dbox-file.c index 2b36013..c714487 100644 --- a/src/lib-storage/index/dbox-common/dbox-file.c +++ b/src/lib-storage/index/dbox-common/dbox-file.c @@ -215,7 +215,7 @@ static int dbox_file_open_full(struct dbox_file *file, bool try_altpath, } } - file->input = i_stream_create_fd(file->fd, DBOX_READ_BLOCK_SIZE, FALSE); + file->input = i_stream_create_fd(file->fd, DBOX_READ_BLOCK_SIZE, TRUE); i_stream_set_name(file->input, file->cur_path); i_stream_set_init_buffer_size(file->input, DBOX_READ_BLOCK_SIZE); return dbox_file_read_header(file); @@ -286,9 +286,12 @@ int dbox_file_header_write(struct dbox_file *file, struct ostream *output) void dbox_file_close(struct dbox_file *file) { dbox_file_unlock(file); - if (file->input != NULL) + if (file->input != NULL) { + /* stream autocloses the fd when it gets destroyed. note that + the stream may outlive the struct dbox_file. */ i_stream_unref(&file->input); - if (file->fd != -1) { + file->fd = -1; + } else if (file->fd != -1) { if (close(file->fd) < 0) dbox_file_set_syscall_error(file, "close()"); file->fd = -1; -- 1.7.10.2 From 7e2d3faf969bcb9f65ae8a7860f4dfff28dd8f95 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 20:53:53 +0300 Subject: [PATCH] istream-[b]zlib: Don't break if parent stream gets seeked in the middle of reads. diff --git a/src/lib-compression/istream-bzlib.c b/src/lib-compression/istream-bzlib.c index 2ad33dc..3937cb1 100644 --- a/src/lib-compression/istream-bzlib.c +++ b/src/lib-compression/istream-bzlib.c @@ -15,7 +15,7 @@ struct bzlib_istream { bz_stream zs; uoff_t eof_offset, stream_size; - size_t prev_size, high_pos; + size_t high_pos; struct stat last_parent_statbuf; unsigned int log_errors:1; @@ -49,7 +49,7 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream) struct bzlib_istream *zstream = (struct bzlib_istream *)stream; const unsigned char *data; uoff_t high_offset; - size_t size; + size_t size, out_size; int ret; high_offset = stream->istream.v_offset + (stream->pos - stream->skip); @@ -98,42 +98,36 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream) } } - if (zstream->zs.avail_in == 0) { - /* need to read more data. try to read a full CHUNK_SIZE */ - i_stream_skip(stream->parent, zstream->prev_size); - if (i_stream_read_data(stream->parent, &data, &size, - CHUNK_SIZE-1) == -1 && size == 0) { - if (stream->parent->stream_errno != 0) { - stream->istream.stream_errno = - stream->parent->stream_errno; - } else { - i_assert(stream->parent->eof); - if (zstream->log_errors) { - bzlib_read_error(zstream, - "unexpected EOF"); - } - stream->istream.stream_errno = EINVAL; - } - return -1; + if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) { + if (stream->parent->stream_errno != 0) { + stream->istream.stream_errno = + stream->parent->stream_errno; + } else { + i_assert(stream->parent->eof); + if (zstream->log_errors) + bzlib_read_error(zstream, "unexpected EOF"); + stream->istream.stream_errno = EINVAL; } - zstream->prev_size = size; - if (size == 0) { - /* no more input */ - i_assert(!stream->istream.blocking); - return 0; - } - - zstream->zs.next_in = (char *)data; - zstream->zs.avail_in = size; + return -1; + } + if (size == 0) { + /* no more input */ + i_assert(!stream->istream.blocking); + return 0; } - size = stream->buffer_size - stream->pos; + zstream->zs.next_in = (char *)data; + zstream->zs.avail_in = size; + + out_size = stream->buffer_size - stream->pos; zstream->zs.next_out = (char *)stream->w_buffer + stream->pos; - zstream->zs.avail_out = size; + zstream->zs.avail_out = out_size; ret = BZ2_bzDecompress(&zstream->zs); - size -= zstream->zs.avail_out; - stream->pos += size; + out_size -= zstream->zs.avail_out; + stream->pos += out_size; + + i_stream_skip(stream->parent, size - zstream->zs.avail_in); switch (ret) { case BZ_OK: @@ -159,7 +153,7 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream) zstream->eof_offset = stream->istream.v_offset + (stream->pos - stream->skip); zstream->stream_size = zstream->eof_offset; - if (size == 0) { + if (out_size == 0) { stream->istream.eof = TRUE; return -1; } @@ -167,11 +161,11 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream) default: i_fatal("BZ2_bzDecompress() failed with %d", ret); } - if (size == 0) { + if (out_size == 0) { /* read more input */ return i_stream_bzlib_read(stream); } - return size; + return out_size; } static void i_stream_bzlib_init(struct bzlib_istream *zstream) @@ -206,7 +200,6 @@ static void i_stream_bzlib_reset(struct bzlib_istream *zstream) stream->skip = stream->pos = 0; stream->istream.v_offset = 0; zstream->high_pos = 0; - zstream->prev_size = 0; (void)BZ2_bzDecompressEnd(&zstream->zs); i_stream_bzlib_init(zstream); diff --git a/src/lib-compression/istream-zlib.c b/src/lib-compression/istream-zlib.c index 021bfe0..c7ac2c4 100644 --- a/src/lib-compression/istream-zlib.c +++ b/src/lib-compression/istream-zlib.c @@ -122,6 +122,7 @@ static int i_stream_zlib_read_header(struct istream_private *stream) pos += 2; } i_stream_skip(stream->parent, pos); + zstream->prev_size = 0; return 1; } @@ -172,7 +173,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream) struct zlib_istream *zstream = (struct zlib_istream *)stream; const unsigned char *data; uoff_t high_offset; - size_t size; + size_t size, out_size; int ret; high_offset = stream->istream.v_offset + (stream->pos - stream->skip); @@ -208,7 +209,6 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream) if (ret <= 0) return ret; zstream->header_read = TRUE; - zstream->prev_size = 0; } if (stream->pos < zstream->high_pos) { @@ -248,44 +248,39 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream) } } - if (zstream->zs.avail_in == 0) { - /* need to read more data. try to read a full CHUNK_SIZE */ - i_stream_skip(stream->parent, zstream->prev_size); - if (i_stream_read_data(stream->parent, &data, &size, - CHUNK_SIZE-1) == -1 && size == 0) { - if (stream->parent->stream_errno != 0) { - stream->istream.stream_errno = - stream->parent->stream_errno; - } else { - i_assert(stream->parent->eof); - if (zstream->log_errors) { - zlib_read_error(zstream, - "unexpected EOF"); - } - stream->istream.stream_errno = EPIPE; - } - return -1; - } - zstream->prev_size = size; - if (size == 0) { - /* no more input */ - i_assert(!stream->istream.blocking); - return 0; + if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) { + if (stream->parent->stream_errno != 0) { + stream->istream.stream_errno = + stream->parent->stream_errno; + } else { + i_assert(stream->parent->eof); + if (zstream->log_errors) + zlib_read_error(zstream, "unexpected EOF"); + stream->istream.stream_errno = EPIPE; } - - zstream->zs.next_in = (void *)data; - zstream->zs.avail_in = size; + return -1; + } + if (size == 0) { + /* no more input */ + i_assert(!stream->istream.blocking); + return 0; } - size = stream->buffer_size - stream->pos; + zstream->zs.next_in = (void *)data; + zstream->zs.avail_in = size; + + out_size = stream->buffer_size - stream->pos; zstream->zs.next_out = stream->w_buffer + stream->pos; - zstream->zs.avail_out = size; + zstream->zs.avail_out = out_size; ret = inflate(&zstream->zs, Z_SYNC_FLUSH); - size -= zstream->zs.avail_out; + out_size -= zstream->zs.avail_out; zstream->crc32 = crc32_data_more(zstream->crc32, - stream->w_buffer + stream->pos, size); - stream->pos += size; + stream->w_buffer + stream->pos, + out_size); + stream->pos += out_size; + + i_stream_skip(stream->parent, size - zstream->zs.avail_in); switch (ret) { case Z_OK: @@ -307,10 +302,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream) zstream->eof_offset = stream->istream.v_offset + (stream->pos - stream->skip); zstream->stream_size = zstream->eof_offset; - i_stream_skip(stream->parent, - zstream->prev_size - zstream->zs.avail_in); zstream->zs.avail_in = 0; - zstream->prev_size = 0; if (!zstream->trailer_read) { /* try to read and verify the trailer, we might not @@ -322,11 +314,11 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream) default: i_fatal("inflate() failed with %d", ret); } - if (size == 0) { + if (out_size == 0) { /* read more input */ return i_stream_zlib_read(stream); } - return size; + return out_size; } static void i_stream_zlib_init(struct zlib_istream *zstream) -- 1.7.10.2 From 7e2ef0020ae79382577f9610d6ab3135bb604b56 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 21:06:00 +0300 Subject: [PATCH] lib-storage: Fixed crash with mailbox_list_index=yes after re-reading index. diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c index 1f2dbed..61391ea 100644 --- a/src/lib-storage/list/mailbox-list-index.c +++ b/src/lib-storage/list/mailbox-list-index.c @@ -27,8 +27,8 @@ void mailbox_list_index_reset(struct mailbox_list_index *ilist) { i_assert(ilist->iter_refcount == 0); - hash_table_clear(ilist->mailbox_names, FALSE); - hash_table_clear(ilist->mailbox_hash, FALSE); + hash_table_clear(ilist->mailbox_names, TRUE); + hash_table_clear(ilist->mailbox_hash, TRUE); p_clear(ilist->mailbox_pool); ilist->mailbox_tree = NULL; ilist->highest_name_id = 0; -- 1.7.10.2 From 249fc7092cf438ee9ca7e2f5cdeb4bd8ff5409e6 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 21:06:34 +0300 Subject: [PATCH] maildir: Crashfix after dovecot-keywords file was re-read. diff --git a/src/lib-storage/index/maildir/maildir-keywords.c b/src/lib-storage/index/maildir/maildir-keywords.c index b45db1c..0a32c45 100644 --- a/src/lib-storage/index/maildir/maildir-keywords.c +++ b/src/lib-storage/index/maildir/maildir-keywords.c @@ -104,7 +104,7 @@ void maildir_keywords_deinit(struct maildir_keywords **_mk) static void maildir_keywords_clear(struct maildir_keywords *mk) { array_clear(&mk->list); - hash_table_clear(mk->hash, FALSE); + hash_table_clear(mk->hash, TRUE); p_clear(mk->pool); } -- 1.7.10.2 From c3df0aec4b12a7aea7fc0a1ec5ca58833862cbb0 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 21:08:31 +0300 Subject: [PATCH] hash_table_clear(): Added a comment about API usage. diff --git a/src/lib/hash.h b/src/lib/hash.h index f0ccb67..ead59a1 100644 --- a/src/lib/hash.h +++ b/src/lib/hash.h @@ -68,8 +68,8 @@ void hash_table_destroy(struct hash_table **table); #define hash_table_destroy(table) \ hash_table_destroy(&(*table)._table) /* Remove all nodes from hash table. If free_collisions is TRUE, the - memory allocated from node_pool is freed, or discarded with - alloconly pools. */ + memory allocated from node_pool is freed, or discarded with alloconly pools. + WARNING: If you p_clear() the node_pool, the free_collisions must be TRUE. */ void hash_table_clear(struct hash_table *table, bool free_collisions); #define hash_table_clear(table, free_collisions) \ hash_table_clear((table)._table, free_collisions) -- 1.7.10.2 From ffdf174645c18d779de5d503df0d7269be42317f Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 21:31:52 +0300 Subject: [PATCH] lib-master: Added master_service_is_master_stopped() diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index 378bc63..a06b6e8 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -600,6 +600,11 @@ bool master_service_is_killed(struct master_service *service) return service->killed; } +bool master_service_is_master_stopped(struct master_service *service) +{ + return service->io_status_error == NULL; +} + void master_service_anvil_send(struct master_service *service, const char *cmd) { ssize_t ret; diff --git a/src/lib-master/master-service.h b/src/lib-master/master-service.h index b975895..0ca002b 100644 --- a/src/lib-master/master-service.h +++ b/src/lib-master/master-service.h @@ -141,6 +141,9 @@ void master_service_stop(struct master_service *service); void master_service_stop_new_connections(struct master_service *service); /* Returns TRUE if we've received a SIGINT/SIGTERM and we've decided to stop. */ bool master_service_is_killed(struct master_service *service); +/* Returns TRUE if our master process is already stopped. This process may or + may not be dying itself. */ +bool master_service_is_master_stopped(struct master_service *service); /* Send command to anvil process, if we have fd to it. */ void master_service_anvil_send(struct master_service *service, const char *cmd); -- 1.7.10.2 From 2598176e416438cbaccd65de471d229651786aec Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 23 Apr 2013 21:32:24 +0300 Subject: [PATCH] stats plugin: Don't try to send notifications to already dead stats process. diff --git a/src/plugins/stats/Makefile.am b/src/plugins/stats/Makefile.am index e7a46d5..a88fc3b 100644 --- a/src/plugins/stats/Makefile.am +++ b/src/plugins/stats/Makefile.am @@ -2,6 +2,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-settings \ -I$(top_srcdir)/src/lib-mail \ + -I$(top_srcdir)/src/lib-master \ -I$(top_srcdir)/src/lib-index \ -I$(top_srcdir)/src/lib-storage diff --git a/src/plugins/stats/stats-connection.c b/src/plugins/stats/stats-connection.c index da07e9b..9560cc4 100644 --- a/src/plugins/stats/stats-connection.c +++ b/src/plugins/stats/stats-connection.c @@ -5,6 +5,7 @@ #include "net.h" #include "str.h" #include "strescape.h" +#include "master-service.h" #include "mail-storage.h" #include "stats-plugin.h" #include "stats-connection.h" @@ -71,6 +72,12 @@ void stats_connection_send(struct stats_connection *conn, const string_t *str) static bool pipe_warned = FALSE; ssize_t ret; + /* if master process has been stopped (and restarted), don't even try + to notify the stats process anymore. even if one exists, it doesn't + know about us. */ + if (master_service_is_master_stopped(master_service)) + return; + if (conn->fd == -1) { if (!stats_connection_open(conn)) return; -- 1.7.10.2