]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Fixed ostream-failure-at with blocking parent stream.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 21 Sep 2016 10:47:05 +0000 (13:47 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 13 Oct 2016 08:15:37 +0000 (10:15 +0200)
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)

src/lib/ostream-failure-at.c

index 2e3cf22d9e88a028e8dd48dd896a208ce50c4da9..bd16c88f84a4030fc9695dd0eaae7fff7107300f 100644 (file)
@@ -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;