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