From: Timo Sirainen Date: Wed, 21 Sep 2016 10:47:05 +0000 (+0300) Subject: lib: Fixed ostream-failure-at with blocking parent stream. X-Git-Tag: 2.3.0.rc1~2995 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a81be83a3bb00b7b31b832f50bd8542e62a71891;p=thirdparty%2Fdovecot%2Fcore.git lib: Fixed ostream-failure-at with blocking parent stream. Blocking ostream returns either a full success or a full failure. It can't return that only n/m bytes were written. Fixes assert: Panic: file ostream.c: line 255 (o_stream_sendv_int): assertion failed: (!stream->blocking) --- diff --git a/src/lib/ostream-failure-at.c b/src/lib/ostream-failure-at.c index 2e3cf22d9e..bd16c88f84 100644 --- a/src/lib/ostream-failure-at.c +++ b/src/lib/ostream-failure-at.c @@ -30,10 +30,23 @@ o_stream_failure_at_sendv(struct ostream_private *stream, unsigned int i; struct const_iovec *iov_dup; unsigned int iov_dup_count; - uoff_t bytes_until_failure; + uoff_t bytes_until_failure, blocking_bytes_count = 0; ssize_t ret; - if (fstream->failure_offset <= stream->ostream.offset) { + if (stream->ostream.blocking) { + /* blocking ostream must return either a full success or a + failure. if the current write would go past failure_offset, + return a failure now before writing anything. */ + for (i = 0; i < iov_count; i++) + blocking_bytes_count += iov[i].iov_len; + if (blocking_bytes_count > 0) { + /* if we're exactly at the failure offset after this + write, fail it only on the next write. */ + blocking_bytes_count--; + } + } + + if (fstream->failure_offset <= stream->ostream.offset + blocking_bytes_count) { io_stream_set_error(&stream->iostream, "%s", fstream->error_string); stream->ostream.stream_errno = errno = EIO;