http2: surface errors occurring very early in a client conn's lifetime

When we create a new connection for a request, the request should
fail if the connection attempt fails.

There is a race condition which can cause this to not happen:

- net/http sends a request to a http2.Transport
- the http2.Transport returns ErrNoCachedConn
- net/http creates a new tls.Conn and passes it to the http2.Transport
- the http2.Transport adds the conn to its connection pool
- the connection immediately encounters an error
- the http2.Transport removes the conn from its connection pool
- net/http resends the request to the http2.Transport
- the http2.Transport returns ErrNoCachedConn, and the process repeates

If the request is sent to the http2.Transport before the connection
encounters an error, then the request fails. But otherwise, we get
stuck in an infinite loop of the http2.Transport asking for a new
connection, receiving one, and throwing it away.

To fix this, leave a dead connection in the pool for a short while
if it has never had a request sent to it. If a dead connection is
used for a new request, return an error and remove the connection
from the pool.

Change-Id: I64eb15a8f1512a6bda52db423072b945fab6f4b5
Reviewed-on: https://go-review.googlesource.com/c/net/+/625398
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
4 files changed
tree: f5bd17ee763fc2d91257fe4a39b37b6864e57107
  1. bpf/
  2. context/
  3. dict/
  4. dns/
  5. html/
  6. http/
  7. http2/
  8. icmp/
  9. idna/
  10. internal/
  11. ipv4/
  12. ipv6/
  13. lif/
  14. nettest/
  15. netutil/
  16. proxy/
  17. publicsuffix/
  18. quic/
  19. route/
  20. trace/
  21. webdav/
  22. websocket/
  23. xsrftoken/
  24. .gitattributes
  25. .gitignore
  26. codereview.cfg
  27. CONTRIBUTING.md
  28. go.mod
  29. go.sum
  30. LICENSE
  31. PATENTS
  32. README.md
README.md

Go Networking

Go Reference

This repository holds supplementary Go networking packages.

Report Issues / Send Patches

This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://go.dev/doc/contribute.

The git repository is https://go.googlesource.com/net.

The main issue tracker for the net repository is located at https://go.dev/issues. Prefix your issue with “x/net:” in the subject line, so it is easy to find.