-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTTP/2: Possible race when receiving HEADERS and RST_STREAM together #68373
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsDescriptionKestrel has recently updated how HTTP/2 is written. One of the changes is to what happens if a request is ended and then the request is immediately reset. At a frame-level, Kestrel is writing a HEADERS frame with an END_HEADERS flag, then writing a RST_STREAM. Before, Kestrel would pause after writing HEADERS, as the bytes are flushed to the client. After the update, Kestrel would write and send the two frames together. In HttpClient, before, SendAsync would always return
The HEADERS frame and RST_STREAM frame are always written in the right order. There appears to be a race between how they're processed. If response headers are returned then SendAsync should always return Reproduction StepsHttpInvoker + SocketsHttpHandler + h2c makes call to server. Expected behaviorHttpResponseMessage is always returned. Actual behaviorHttpInvoker.SendAsync fails 10% of the time with an error. Regression?Probably not. Known WorkaroundsNo response Configuration.NET SDK 7.0.100-preview.5.22221.9 Other informationLogging of success (HttpResponseMessage returned):
Failure (error thrown):
|
cc @davidfowl |
@JamesNK We are in process of .NET 7 Preview 4 Validation window, it should be signed off by 4/29. Our test cases failed by this bug. Could you please confirm whether this issue is a blocker for Preview 4? Thanks. |
Not a blocker. Anyone impacted can update to the latest version of gRPC which shouldn't be affected. |
Yep, there's a race here:
I think this can be fixed by changing the order of checks in |
Triage: Sounds reasonable to fix it and not throw in technically valid response. |
Hi together, Could this issue also explain the following behaviour we observed using the grpc-dotnet client (version 2.46.0) ? If a HTTP2 connection is closed by the server by sending a GOAWAY frame to the client we sometimes observe the following error in the logs:
After this we get a "Incomplete message" response in the client
Sadly i haven't been able to create a reproducer as the issue occurs very seldom and only after some time of running the application. |
Happens on .NET 7? |
Sorry forgot to mention its happening on .NET 6 (6.0.202) SDK |
Does this particular message sends any content? Do you have custom content? |
The request is a unary grpc call sending a request containing some bytes |
@JamesNK is is possible that gRPC |
The client is reporting an "Incomplete message" which seems to indicate it's an incomplete response body (according to the client) rather than in incomplete request body. |
I think the client is receiving a response from the server with grpc-status 13 and the message
so for me it looks like the server received an incomplete request and replied with an error or am i missing something ? |
Hi, |
I'd suggest filing issue in grpc repo for your particular problem, doesn't seem to be directly related. |
Description
Kestrel has recently updated how HTTP/2 is written. One of the changes is to what happens if a request is ended and then the request is immediately reset. At a frame-level, Kestrel is writing a HEADERS frame with an END_HEADERS flag, then writing a RST_STREAM. Before, Kestrel would pause after writing HEADERS, as the bytes are flushed to the client. After the update, Kestrel would write and send the two frames together.
In HttpClient, before, SendAsync would always return
HttpResponseMessage
. With the new server behavior, SendAsync continues to returnHttpResponseMessage
(about 90% of the time). Other times it throws an error:The HEADERS frame and RST_STREAM frame are always written in the right order. There appears to be a race between how they're processed.
If response headers are returned then SendAsync should always return
HttpResponseMessage
, regardless of the fact it is followed by RST_STREAM.Reproduction Steps
HttpInvoker + SocketsHttpHandler + h2c makes call to server.
The server writes response headers with HEADERS frame and END_STREAM flag, together with RST_STREAM (NO_ERROR).The server
Expected behavior
HttpResponseMessage is always returned.
Actual behavior
HttpInvoker.SendAsync fails 10% of the time with an error.
Regression?
Probably not. Kestrel has changed in .NET 7, but I believe the timing of how it sends frames has exposed a race that has been in the client's HTTP/2 processing.
Known Workarounds
No response
Configuration
.NET SDK 7.0.100-preview.5.22221.9
Other information
Logs below. Truncated to just show the end of the request.
Logging of success (HttpResponseMessage returned):
Failure (error thrown):
The text was updated successfully, but these errors were encountered: