]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: ostream-multiplex - Call flush callbacks also when stream has failed
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 20 Jan 2022 13:13:48 +0000 (14:13 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Tue, 25 Jan 2022 09:14:27 +0000 (09:14 +0000)
It may be important for the flush callbacks to know when ostream has been
closed. This is a partial fix to prevent doveadm-server hanging when it's
printing lots of output and doveadm client disconnects.

src/lib/ostream-multiplex.c

index 30cdccc166f141696bfff7aa329a285ca48cd87b..6c3bf8536e96acf682eacc1e7adb2d6bcee1bff6 100644 (file)
@@ -121,25 +121,26 @@ static int o_stream_multiplex_flush(struct multiplex_ostream *mstream)
        int ret = o_stream_flush(mstream->parent);
        if (ret >= 0) {
                if (!o_stream_multiplex_sendv(mstream))
-                       ret = 0;
+                       return 0;
        }
-       if (ret <= 0)
-               return ret;
 
-       /* Everything is flushed. See if one of the callbacks' flush callbacks
-          wants to write more data. */
+       /* a) Everything is flushed. See if one of the callbacks' flush
+          callbacks wants to write more data.
+          b) ostream failed. Notify the callbacks in case they need to know. */
        struct multiplex_ochannel *channel;
        bool unfinished = FALSE;
+       bool failed = FALSE;
        array_foreach_elem(&mstream->channels, channel) {
                if (channel != NULL && channel->ostream.callback != NULL) {
                        ret = channel->ostream.callback(channel->ostream.context);
                        if (ret < 0)
-                               return -1;
-                       if (ret == 0)
+                               failed = TRUE;
+                       else if (ret == 0)
                                unfinished = TRUE;
                }
        }
-       return unfinished ? 0 : 1;
+       return failed ? -1 :
+               (unfinished ? 0 : 1);
 }
 
 static int o_stream_multiplex_ochannel_flush(struct ostream_private *stream)