On Thu, Sep 14, 2023 at 12:35 PM Christopher Faulet <cfau...@haproxy.com> wrote:
> After a discussion with Willy, we've hopefully found a way to fix the issue by
> delaying detection of the server abort on the request processing side when 
> there
> is a response to forward to the client. It should do the trick in your case 
> and
> it should be safe.
>
> However, the fix remains sensitive. It is really hard to be sure it will not
> introduce a regression. The worst could be to block a session or to get a loop
> because of an unhandled event.
>
> Thus it could be go to test it on your side if it is possible. The patch is in
> attachment. It can be applied on top of the 2.9 or 2.8. Is this possible for 
> you ?

I applied the patch on top of v2.9-dev5. For what it's worth, I build
on Ubuntu 22.04 with defaults from INSTALL: TARGET=linux-glibc
USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1 USE_SYSTEMD=1.

The delayed processing patch does not appear to change anything for
me. I am still seeing HTTP 502 (Bad Gateway) and HAProxy logs report
session state as SH--. According to documentation, that is "the TCP
session was unexpectedly aborted by the server, or the server
explicitly refused it" together with "the proxy was waiting for
complete, valid response HEADERS from the server (HTTP only)".
Somehow, if the H2 connection to backend is half-open(local), HAProxy
is expecting more HEADERS from the backend server.

I am providing a short diff below, which force-closes the H2
connection to backend upon remote ES (which would break long-running
upload from frontend to client). The change is interesting, because it
highlights something weird with processing. Without this change, even
with your provided patch, HAProxy never finishes processing HEADERS.
However, with this change, response is delivered to the frontend
client when the stream closes.

The session state is probably not relevant, but for what it's worth,
it becomes CL--. C for "the TCP session was unexpectedly aborted by
the client" -- not sure why unexpectedly, because from the client side
everything received successfully -- and L for "the proxy was still
transmitting LAST data to the client while the server had already
finished. This one is very rare as it can only happen when the client
dies while receiving the last packets". Maybe this gives some other
ideas.

diff --git a/src/mux_h2.c b/src/mux_h2.c
index cc698b66b..c1ff014dd 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -2934,7 +2934,7 @@ static struct h2s *h2c_bck_handle_headers(struct
h2c *h2c, struct h2s *h2s)
        else if (h2s->flags & H2_SF_ES_RCVD) {
                if (h2s->st == H2_SS_OPEN)
                        h2s->st = H2_SS_HREM;
-               else if (h2s->st == H2_SS_HLOC)
+               if (h2s->st == H2_SS_HLOC || h2s->st == H2_SS_HREM)
                        h2s_close(h2s);
        }

The clients should send proper and timely END_STREAMs, so this should
not be a major issue, but something still feels strange here with
connection state processing.

Let me know if I can help brainstorm this further.

Best regards,
Valters Jansons

Reply via email to