-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/net/http2: the first write error on a connection will cause all subsequent write requests to fail blindly #39337
Comments
/cc @bradfitz @tombergan @rsc |
cc @fraenkel |
There is a missing MarkDead on the connection. The current code only does cleanup if we start the readLoop which never happens. |
Sorry, I did some further digging. It seems the readLoop is entered but never exits which is why the cleanup never occurs as expected. |
@bradfitz It doesn't seem like the http2 tranport handles write errors properly. I see that the error is recorded and it flows up to the client, but I don't see any place that would tear the connection down. Is the assumption that a read failure must occur? It seems a bit difficult if the server side is mishandling requests like this test case does. |
Change https://golang.org/cl/240337 mentions this issue: |
HTTP/2 support is golang has many problematic cornercases where dead connections would be kept. golang/go#32388 golang/go#39337 golang/go#39750 I suggest we disable HTTP/2 for now and enable it manually on the blackbox exporter. Signed-off-by: Julien Pivotto <[email protected]>
@gopherbot, please backport. I think this is pretty bad. (It bit us and there's no great workaround, short of disabling HTTP/2) |
Backport issue(s) opened: #42112 (for 1.14), #42113 (for 1.15). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases. |
To/for f5854403a9740e74b2e9e725e6cd7c8a57711905 https://go-review.googlesource.com/c/net/+/240337 golang#39337 Updates tailscale/tailscale#839
Given that golang/go#39337 and golang/go#40201 are fixed: - We now have a function to configure HTTP/2 transport, therefore we have a "ping" every 5 minutes on the line if not traffic is doing on - Dead HTTP/2 connections will be removed from the pool Signed-off-by: Julien Pivotto <[email protected]>
Change https://golang.org/cl/266157 mentions this issue: |
Change https://golang.org/cl/266158 mentions this issue: |
…rors When a new connection is created, and a write error occurs during the initial exchange, the connection must be closed. There is no guarantee that the caller will close the connection. When a connection with an existing write error is used or being used, it will stay in use until its read loop completes. Requests will continue to use this connection and fail when writing its header. These connections should be closed to force the cleanup in its readLoop. Updates golang/go#39337. For golang/go#42112. Change-Id: I45e1293309e40629531f4cbb69387864f4f71bc2 Reviewed-on: https://go-review.googlesource.com/c/net/+/240337 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Brad Fitzpatrick <[email protected]> Trust: Damien Neil <[email protected]> (cherry picked from commit f585440) Reviewed-on: https://go-review.googlesource.com/c/net/+/266157 Trust: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: Michael Fraenkel <[email protected]> Reviewed-by: Alexander Rakoczy <[email protected]>
…rite errors When a new connection is created, and a write error occurs during the initial exchange, the connection must be closed. There is no guarantee that the caller will close the connection. When a connection with an existing write error is used or being used, it will stay in use until its read loop completes. Requests will continue to use this connection and fail when writing its header. These connections should be closed to force the cleanup in its readLoop. Updates golang/go#39337. For golang/go#42113. Change-Id: I45e1293309e40629531f4cbb69387864f4f71bc2 Reviewed-on: https://go-review.googlesource.com/c/net/+/240337 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Brad Fitzpatrick <[email protected]> Trust: Damien Neil <[email protected]> (cherry picked from commit f585440) Reviewed-on: https://go-review.googlesource.com/c/net/+/266158 Trust: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]>
Change https://golang.org/cl/266374 mentions this issue: |
Change https://golang.org/cl/266375 mentions this issue: |
Bring in the change in CL 266157 with: go get -d golang.org/x/[email protected] go mod tidy go mod vendor go generate -run=bundle std Updates #39337. Fixes #42112. Change-Id: Iefd0012369c7f0c58201256e29d21210cb9f2f7a Reviewed-on: https://go-review.googlesource.com/c/go/+/266374 Run-TryBot: Dmitri Shuralyov <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Dmitri Shuralyov <[email protected]>
Bring in the change in CL 266158 with: go mod edit -replace=golang.org/x/net=golang.org/x/[email protected] GOFLAGS='-mod=mod' go generate -run=bundle std go mod edit -dropreplace=golang.org/x/net go get -d golang.org/x/[email protected] go mod tidy go mod vendor Updates #39337. Fixes #42113. Change-Id: I3ebef4b90c11ad271b7a3031aafd80c423c2c241 Reviewed-on: https://go-review.googlesource.com/c/go/+/266375 Trust: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]>
When a new connection is created, and a write error occurs during the initial exchange, the connection must be closed. There is no guarantee that the caller will close the connection. When a connection with an existing write error is used or being used, it will stay in use until its read loop completes. Requests will continue to use this connection and fail when writing its header. These connections should be closed to force the cleanup in its readLoop. Fixes golang/go#39337 Change-Id: I45e1293309e40629531f4cbb69387864f4f71bc2 Reviewed-on: https://go-review.googlesource.com/c/net/+/240337 Reviewed-by: Brad Fitzpatrick <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Brad Fitzpatrick <[email protected]> Trust: Damien Neil <[email protected]>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Here is a test that reproduces the issue: https://github.com/jaricftw/go-http2-stuck-transport/blob/master/conn_write_timeout_test.go#L19
It tests the TCP write deadline behavior with Go HTTP2 library.
Server setup: a blocking TCP server, i.e. connection can be established, but never read data from the connection.
Client setup: An http2 client makes calls to the blocking TCP server. TCP write timeout (using https://golang.org/pkg/net/#TCPConn.SetWriteDeadline) is set for each
Write
operation of a connection. TCP write buffer is also set to be small to quickly fill up the write buffer of the client.What did you expect to see?
Each request will get stuck and eventually time out after the specified TCP write timeout (i.e. 2 seconds)
What did you see instead?
First request times out after the specified 2 seconds, as expected
However, any subsequent request returns immediately with the same error:
This indicates:
Dug into the http2 transport implementation, this is likely because the first write error on the connection will make all future
writeHeaders
to fail with the same error immediately:ref: https://github.com/golang/net/blob/master/http2/transport.go#L1245
The text was updated successfully, but these errors were encountered: