Hello,

I was previously investigating a strange gRPC streaming issue, that
appears to be a fairly straight forward issue with how open streams
get half-closed.

In a nice situation, a frontend request comes in and has END_STREAM
marked. The frontend becomes half-closed by the remote side. In turn,
the backend gets half-closed by HAProxy on the local side. When the
backend response has END_STREAM, it triggers the stream to nicely
close, calling h2s_close. The response is then delivered to the
requestor at the frontend.

However, if the request on frontend does not have END_STREAM, then the
backend also stays open. When the backend sends a response (H2 HEADERS
frame) with END_STREAM, the H2 stream is updated to "half-closed
(remote)" but it is never properly considered closed. The server
thinks all has been processed, and can send a RST_STREAM afterwards,
but the actual response is not delivered to the frontend side.
Instead, HTTP 502 is sent to the original requestor, and the session
disconnect state is reported as SH--.

In my scenario, there is only a HEADERS frame, so
`h2c_bck_handle_headers` can be modified as to `h2s_close` on
`H2_SS_HREM` (starting out as `H2_SS_OPEN`) in addition to
`H2_SS_HLOC`. This is a hacky solution however, and would not address
a DATA frame having the same issue. Instead, the actual response
should be properly processed when the backend remote closes its side
(instead of waiting on frontend to close its side).

I will try to loop back around to this issue, with a patch. But that
will most likely take time from my side both due to limited personal
bandwidth and unfamiliarity with the H2 processing. Anyone willing to
provide a quicker patch is appreciated!

---

Trace excerpt:

[00|h2|2|mux_h2.c:3612] receiving H2 HEADERS frame :
h2c=0x560dddb99c50(B,FRP) h2s=0x560dddb064a0(1,OPN)
[00|h2|5|mux_h2.c:2876] h2c_bck_handle_headers(): entering :
h2c=0x560dddb99c50(B,FRP) h2s=0x560dddb064a0(1,OPN)
[00|h2|5|mux_h2.c:4898] h2c_dec_hdrs(): entering : h2c=0x560dddb99c50(B,FRP)
[00|h2|1|mux_h2.c:5040] h2c_dec_hdrs(): h2c=0x560dddb99c50(B,FRP)
dsi=1 rcvh :status: 200
[00|h2|1|mux_h2.c:5040] h2c_dec_hdrs(): h2c=0x560dddb99c50(B,FRP)
dsi=1 rcvh content-type: application/grpc
[00|h2|1|mux_h2.c:5040] h2c_dec_hdrs(): h2c=0x560dddb99c50(B,FRP)
dsi=1 rcvh grpc-status: 12
[00|h2|1|mux_h2.c:5040] h2c_dec_hdrs(): h2c=0x560dddb99c50(B,FRP)
dsi=1 rcvh grpc-message: unknown service
grpc.reflection.v1.ServerReflection
[00|h2|5|mux_h2.c:5146] h2c_dec_hdrs(): leaving : h2c=0x560dddb99c50(B,FRH)
[00|h2|1|mux_h2.c:2951] rcvd H2 response  : h2c=0x560dddb99c50(B,FRH)
: [1] H2 RES: HTTP/2.0 200
[00|h2|5|mux_h2.c:2952] h2c_bck_handle_headers(): leaving :
h2c=0x560dddb99c50(B,FRH) h2s=0x560dddb064a0(1,HCR)
---

Best regards,
Valters Jansons

Reply via email to