Commit 7e394a23 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick Committed by Tom Bergan

net/http: update bundled http2

Updates http2 to x/net git rev 894f8ed58 for:

    http2: fix flake in net/http's TestCloseIdleConnections_h2
    https://golang.org/cl/80139

    http2: fix leak in activeRes by removing activeRes
    https://golang.org/cl/80137

Fixes #22413
Fixes #21543

Change-Id: Ic8ea20f8ddae2fde17884ed045f9fa7058a4bd23
Reviewed-on: https://go-review.googlesource.com/81276
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarTom Bergan <tombergan@google.com>
parent b53088a6
...@@ -7926,17 +7926,12 @@ func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStr ...@@ -7926,17 +7926,12 @@ func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStr
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
type http2clientConnReadLoop struct { type http2clientConnReadLoop struct {
cc *http2ClientConn cc *http2ClientConn
activeRes map[uint32]*http2clientStream // keyed by streamID
closeWhenIdle bool closeWhenIdle bool
} }
// readLoop runs in its own goroutine and reads and dispatches frames. // readLoop runs in its own goroutine and reads and dispatches frames.
func (cc *http2ClientConn) readLoop() { func (cc *http2ClientConn) readLoop() {
rl := &http2clientConnReadLoop{ rl := &http2clientConnReadLoop{cc: cc}
cc: cc,
activeRes: make(map[uint32]*http2clientStream),
}
defer rl.cleanup() defer rl.cleanup()
cc.readerErr = rl.run() cc.readerErr = rl.run()
if ce, ok := cc.readerErr.(http2ConnectionError); ok { if ce, ok := cc.readerErr.(http2ConnectionError); ok {
...@@ -7991,10 +7986,8 @@ func (rl *http2clientConnReadLoop) cleanup() { ...@@ -7991,10 +7986,8 @@ func (rl *http2clientConnReadLoop) cleanup() {
} else if err == io.EOF { } else if err == io.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }
for _, cs := range rl.activeRes {
cs.bufPipe.CloseWithError(err)
}
for _, cs := range cc.streams { for _, cs := range cc.streams {
cs.bufPipe.CloseWithError(err) // no-op if already closed
select { select {
case cs.resc <- http2resAndError{err: err}: case cs.resc <- http2resAndError{err: err}:
default: default:
...@@ -8072,7 +8065,7 @@ func (rl *http2clientConnReadLoop) run() error { ...@@ -8072,7 +8065,7 @@ func (rl *http2clientConnReadLoop) run() error {
} }
return err return err
} }
if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { if rl.closeWhenIdle && gotReply && maybeIdle {
cc.closeIfIdle() cc.closeIfIdle()
} }
} }
...@@ -8080,6 +8073,13 @@ func (rl *http2clientConnReadLoop) run() error { ...@@ -8080,6 +8073,13 @@ func (rl *http2clientConnReadLoop) run() error {
func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) error { func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) error {
cc := rl.cc cc := rl.cc
cs := cc.streamByID(f.StreamID, false)
if cs == nil {
// We'd get here if we canceled a request while the
// server had its response still in flight. So if this
// was just something we canceled, ignore it.
return nil
}
if f.StreamEnded() { if f.StreamEnded() {
// Issue 20521: If the stream has ended, streamByID() causes // Issue 20521: If the stream has ended, streamByID() causes
// clientStream.done to be closed, which causes the request's bodyWriter // clientStream.done to be closed, which causes the request's bodyWriter
...@@ -8088,14 +8088,15 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro ...@@ -8088,14 +8088,15 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro
// Deferring stream closure allows the header processing to occur first. // Deferring stream closure allows the header processing to occur first.
// clientConn.RoundTrip may still receive the bodyWriter error first, but // clientConn.RoundTrip may still receive the bodyWriter error first, but
// the fix for issue 16102 prioritises any response. // the fix for issue 16102 prioritises any response.
defer cc.streamByID(f.StreamID, true) //
} // Issue 22413: If there is no request body, we should close the
cs := cc.streamByID(f.StreamID, false) // stream before writing to cs.resc so that the stream is closed
if cs == nil { // immediately once RoundTrip returns.
// We'd get here if we canceled a request while the if cs.req.Body != nil {
// server had its response still in flight. So if this defer cc.forgetStreamID(f.StreamID)
// was just something we canceled, ignore it. } else {
return nil cc.forgetStreamID(f.StreamID)
}
} }
if !cs.firstByte { if !cs.firstByte {
if cs.trace != nil { if cs.trace != nil {
...@@ -8128,9 +8129,6 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro ...@@ -8128,9 +8129,6 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro
// (nil, nil) special case. See handleResponse docs. // (nil, nil) special case. See handleResponse docs.
return nil return nil
} }
if res.Body != http2noBody {
rl.activeRes[cs.ID] = cs
}
cs.resTrailer = &res.Trailer cs.resTrailer = &res.Trailer
cs.resc <- http2resAndError{res: res} cs.resc <- http2resAndError{res: res}
return nil return nil
...@@ -8469,7 +8467,6 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err ...@@ -8469,7 +8467,6 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err
rl.closeWhenIdle = true rl.closeWhenIdle = true
} }
cs.bufPipe.closeWithErrorAndCode(err, code) cs.bufPipe.closeWithErrorAndCode(err, code)
delete(rl.activeRes, cs.ID)
select { select {
case cs.resc <- http2resAndError{err: err}: case cs.resc <- http2resAndError{err: err}:
...@@ -8596,7 +8593,6 @@ func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) er ...@@ -8596,7 +8593,6 @@ func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) er
cs.bufPipe.CloseWithError(err) cs.bufPipe.CloseWithError(err)
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
} }
delete(rl.activeRes, cs.ID)
return nil return nil
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment