1 From 7a883f8542dffb7299a903eb9a82fed3980337fa Mon Sep 17 00:00:00 2001
2 From: Willy Tarreau <w@1wt.eu>
3 Date: Sat, 20 Oct 2012 10:38:09 +0200
4 Subject: BUG/MEDIUM: http: set DONTWAIT on data when switching to tunnel mode
6 Jaroslaw Bojar diagnosed an issue when haproxy switches to tunnel mode
7 after a transfer. The response data are sent with the MSG_MORE flag,
8 causing them to be needlessly queued in the kernel. In order to fix this,
9 we set the CF_NEVER_WAIT flag on the channels when switching to tunnel
12 One issue remained with client-side keep-alive : if the response is sent
13 before the end of the request, it suffers the same issue for the same
14 reason. This is easily addressed by setting the CF_SEND_DONTWAIT flag
15 on the channel when the response has been parsed and we're waiting for
18 The same issue is present in 1.4 so the fix must be backported.
19 (cherry picked from commit fc47f91c9cc66e3652d98deab82d6e5fe3a59711)
21 src/proto_http.c | 10 ++++++++++
22 1 files changed, 10 insertions(+), 0 deletions(-)
24 diff --git a/src/proto_http.c b/src/proto_http.c
25 index dc65cbd..2ba38f1 100644
26 --- a/src/proto_http.c
27 +++ b/src/proto_http.c
28 @@ -4178,6 +4178,7 @@ int http_sync_req_state(struct session *s)
29 /* if any side switches to tunnel mode, the other one does too */
30 buffer_auto_read(buf);
31 txn->req.msg_state = HTTP_MSG_TUNNEL;
32 + buf->flags |= BF_NEVER_WAIT;
36 @@ -4211,6 +4212,7 @@ int http_sync_req_state(struct session *s)
38 buffer_auto_read(buf);
39 txn->req.msg_state = HTTP_MSG_TUNNEL;
40 + buf->flags |= BF_NEVER_WAIT;
43 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {
44 @@ -4297,6 +4299,7 @@ int http_sync_res_state(struct session *s)
45 /* if any side switches to tunnel mode, the other one does too */
46 buffer_auto_read(buf);
47 txn->rsp.msg_state = HTTP_MSG_TUNNEL;
48 + buf->flags |= BF_NEVER_WAIT;
52 @@ -4334,6 +4337,7 @@ int http_sync_res_state(struct session *s)
54 buffer_auto_read(buf);
55 txn->rsp.msg_state = HTTP_MSG_TUNNEL;
56 + buf->flags |= BF_NEVER_WAIT;
59 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {
60 @@ -4379,6 +4383,12 @@ int http_sync_res_state(struct session *s)
63 http_silent_debug(__LINE__, s);
65 + /* We force the response to leave immediately if we're waiting for the
66 + * other side, since there is no pending shutdown to push it out.
68 + if (!(buf->flags & BF_OUT_EMPTY))
69 + buf->flags |= BF_SEND_DONTWAIT;
70 return txn->rsp.msg_state != old_state || buf->flags != old_flags;