diff options
| author | Michael Anthony Knyszek <mknyszek@google.com> | 2024-12-05 21:52:49 +0000 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-12-06 18:34:31 +0000 |
| commit | 18bbcffc46ce9d681190562f9430cd6727978254 (patch) | |
| tree | 0945a720e31ee41172ee3a1f94b5ef9f1640d81b /src/net/http | |
| parent | 98534fd1a0dbb354a5e10d3de3a58ebdcfd2b5f6 (diff) | |
| download | go-18bbcffc46ce9d681190562f9430cd6727978254.tar.xz | |
all: update vendored dependencies [generated]
The Go 1.24 RC is due for next week. This is a time to once again update
all golang.org/x/... module versions that contribute packages to the
std and cmd modules in the standard library to latest master versions.
For #36905.
[git-generate]
go install golang.org/x/build/cmd/updatestd@latest
go install golang.org/x/tools/cmd/bundle@latest
updatestd -goroot=$(pwd) -branch=master
Change-Id: If4fd03a18590ff3b6e701a9698370c57c69979c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/634041
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Diffstat (limited to 'src/net/http')
| -rw-r--r-- | src/net/http/h2_bundle.go | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 6186d609c2..46a2b79231 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -7813,6 +7813,16 @@ type http2ClientConn struct { pingTimeout time.Duration extendedConnectAllowed bool + // rstStreamPingsBlocked works around an unfortunate gRPC behavior. + // gRPC strictly limits the number of PING frames that it will receive. + // The default is two pings per two hours, but the limit resets every time + // the gRPC endpoint sends a HEADERS or DATA frame. See golang/go#70575. + // + // rstStreamPingsBlocked is set after receiving a response to a PING frame + // bundled with an RST_STREAM (see pendingResets below), and cleared after + // receiving a HEADERS or DATA frame. + rstStreamPingsBlocked bool + // pendingResets is the number of RST_STREAM frames we have sent to the peer, // without confirming that the peer has received them. When we send a RST_STREAM, // we bundle it with a PING frame, unless a PING is already in flight. We count @@ -9153,10 +9163,14 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) { ping := false if !closeOnIdle { cc.mu.Lock() - if cc.pendingResets == 0 { - ping = true + // rstStreamPingsBlocked works around a gRPC behavior: + // see comment on the field for details. + if !cc.rstStreamPingsBlocked { + if cc.pendingResets == 0 { + ping = true + } + cc.pendingResets++ } - cc.pendingResets++ cc.mu.Unlock() } cc.writeStreamReset(cs.ID, http2ErrCodeCancel, ping, err) @@ -9905,7 +9919,7 @@ func (rl *http2clientConnReadLoop) run() error { cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err) } if se, ok := err.(http2StreamError); ok { - if cs := rl.streamByID(se.StreamID); cs != nil { + if cs := rl.streamByID(se.StreamID, http2notHeaderOrDataFrame); cs != nil { if se.Cause == nil { se.Cause = cc.fr.errDetail } @@ -9960,7 +9974,7 @@ func (rl *http2clientConnReadLoop) run() error { } func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) error { - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, http2headerOrDataFrame) if cs == nil { // We'd get here if we canceled a request while the // server had its response still in flight. So if this @@ -10289,7 +10303,7 @@ func (b http2transportResponseBody) Close() error { func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error { cc := rl.cc - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, http2headerOrDataFrame) data := f.Data() if cs == nil { cc.mu.Lock() @@ -10424,9 +10438,22 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err cs.abortStream(err) } -func (rl *http2clientConnReadLoop) streamByID(id uint32) *http2clientStream { +// Constants passed to streamByID for documentation purposes. +const ( + http2headerOrDataFrame = true + http2notHeaderOrDataFrame = false +) + +// streamByID returns the stream with the given id, or nil if no stream has that id. +// If headerOrData is true, it clears rst.StreamPingsBlocked. +func (rl *http2clientConnReadLoop) streamByID(id uint32, headerOrData bool) *http2clientStream { rl.cc.mu.Lock() defer rl.cc.mu.Unlock() + if headerOrData { + // Work around an unfortunate gRPC behavior. + // See comment on ClientConn.rstStreamPingsBlocked for details. + rl.cc.rstStreamPingsBlocked = false + } cs := rl.cc.streams[id] if cs != nil && !cs.readAborted { return cs @@ -10561,7 +10588,7 @@ func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame) func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error { cc := rl.cc - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, http2notHeaderOrDataFrame) if f.StreamID != 0 && cs == nil { return nil } @@ -10590,7 +10617,7 @@ func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame } func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) error { - cs := rl.streamByID(f.StreamID) + cs := rl.streamByID(f.StreamID, http2notHeaderOrDataFrame) if cs == nil { // TODO: return error if server tries to RST_STREAM an idle stream return nil @@ -10668,6 +10695,7 @@ func (rl *http2clientConnReadLoop) processPing(f *http2PingFrame) error { if cc.pendingResets > 0 { // See clientStream.cleanupWriteRequest. cc.pendingResets = 0 + cc.rstStreamPingsBlocked = true cc.cond.Broadcast() } return nil |
