Mercurial > dovecot > core-2.2
changeset 20799:a46ba877e377
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)
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 21 Sep 2016 13:47:05 +0300 |
parents | 2260cbf542c2 |
children | c2bbdca09f56 |
files | src/lib/ostream-failure-at.c |
diffstat | 1 files changed, 15 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/ostream-failure-at.c Mon Sep 19 11:08:08 2016 +0300 +++ b/src/lib/ostream-failure-at.c Wed Sep 21 13:47:05 2016 +0300 @@ -30,10 +30,23 @@ 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;