-
Notifications
You must be signed in to change notification settings - Fork 18k
x/net/http2: reads client request body after close #71782
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
Comments
so it only checks that the body was closed after it receives an error from read: https://go.googlesource.com/net/+/5095d0cf1463414ad99ced9d5032eae6175f5ac5/http2/transport.go#1908 which seems fine? NewRequestWithContext states that https://pkg.go.dev/net/http#NewRequestWithContext
note the "possibly asynchronously" it could check before every attempt to read, but that feels like a possibly high performance hit for something that should be fine. |
I can convince myself that it is fine to return an error from However, we have a different scenario here. The transport closes the reader, and keeps reading from it. There is no way asynchronicity can be an excuse for such behaviour. |
it closes the reader expecting that closed readers return an error that allows it to stop copying (similar to how you might interrupt an ongoing io.Copy) |
@seankhliao this is unbelievably poor requirement and I'm sure incorrect one:
|
http.Client.Do returning is not sufficient: http supports bidirectional communications, returning only means a connection has been established. |
I do not get your reasoning. In my example there is no bidirectional communication. There is not even a |
The
A concurrent call means that This implies that a request body cannot be reused across requests. If the request body contains some resource (such as an |
Ok, but how do I know when I may create another single-use wrapper around a reusable reader? It is only possible when the first single-use wrapper is done with reads. But, when An example of a read that runs after an error is returned from
Btw., the documentation only tells that |
Arrange for the wrapper (the |
This is broken. As I showed in #71782 (comment), it is possible that a read from the request body be in progress after
Every user of |
The client could wait for any reads from the request body to complete before returning an error from
|
Go version
5095d0cf1463414ad99ced9d5032eae6175f5ac5
Output of
go env
in your module/workspace:What did you do?
In a program of mine I have a reader that happens to validate that no accesses are made to it after it is closed. If this reader is passed as
Request.Body
to a HTTP/2 client, it sometimes detects a use-after-close if the request context is canceled half-way through. Here is a reproducer that can be added as a test tox/net/http2
. While writing it, I found it out that there are in fact two failure modes in the HTTP/2 transport:RoundTrip()
returns an error, butcs.doRequest()
keeps reading from the request body,RoundTrip()
keeps reading from the request body after it calls tocloseReqBodyLocked()
.Here is the reproducer. On my machine, 4 runs of every scenario are enough to hit the race. You may need to increase that number.
What did you see happen?
HTTP/2 transport keeps reading from a closed
Request.Body
.What did you expect to see?
HTTP/2 transport must make no reads from
Request.Body
afterRoundTrip()
returns.The text was updated successfully, but these errors were encountered: