]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: channel: don't allow to overwrite the reserve until connected
authorWilly Tarreau <w@1wt.eu>
Wed, 20 Apr 2016 18:09:22 +0000 (20:09 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 21 Apr 2016 13:31:22 +0000 (15:31 +0200)
Commit 9c06ee4 ("BUG/MEDIUM: channel: don't schedule data in transit for
leaving until connected") took care of an issue involving POST in conjunction
with http-send-name-header, where we absolutely never want to touch the
reserve until we're sure not to touch the buffer contents anymore, which
is indicated by the output stream-interface being connected.

But channel_may_recv() was not equipped with such a test, so in some
situations it might decide that it is possible to poll for reads, and
later channel_recv_limit() will decide it's not possible to read,
causing a loop. So we must add a similar test there.

Since the fix above was backported to 1.6 and 1.5, this fix must as well.

include/proto/channel.h

index 31993faf4599f050f16e14f42b3cc8c2f7832acc..76754e18ff6a8fe9339af85f361fac4d4ceab522 100644 (file)
@@ -165,7 +165,9 @@ static inline int channel_may_send(const struct channel *chn)
  * end of transfer is close to happen. Note that both ->buf->o and ->to_forward
  * are considered as available since they're supposed to leave the buffer. The
  * test is optimized to avoid as many operations as possible for the fast case
- * and to be used as an "if" condition.
+ * and to be used as an "if" condition. Just like channel_recv_limit(), we
+ * never allow to overwrite the reserve until the output stream interface is
+ * connected, otherwise we could spin on a POST with http-send-name-header.
  */
 static inline int channel_may_recv(const struct channel *chn)
 {
@@ -179,6 +181,9 @@ static inline int channel_may_recv(const struct channel *chn)
        if (!rem)
                return 0; /* buffer already full */
 
+       if (rem <= global.tune.maxrewrite && !channel_may_send(chn))
+               return 0;
+
        /* now we know there's some room left, verify if we're touching
         * the reserve with some permanent input data.
         */