aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2017-06-19 22:59:56 +0000
committerBrad Fitzpatrick <bradfitz@golang.org>2017-06-19 23:26:32 +0000
commitbe855e3f28507dd3e34eb4699c84493eeaae68db (patch)
treedead2febec862e78803e337cdad162c86bbb01bd
parent26b07c43a3b160d06ed48657aeea40c84f21078d (diff)
downloadgo-be855e3f28507dd3e34eb4699c84493eeaae68db.tar.xz
net/http: update bundled http2
Updates http2 to x/net/http2 git rev 3d7ac2a5d for: http2: fix Server race https://golang.org/cl/20704 Fixes #20704 Change-Id: I803288f94a8a462ad0960b0c29c2dfee27b9f1ae Reviewed-on: https://go-review.googlesource.com/46093 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Tom Bergan <tombergan@google.com> Reviewed-by: Tom Bergan <tombergan@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/net/http/h2_bundle.go19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index 0533f56f0e..9ef24ab6cc 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -5946,6 +5946,7 @@ type http2responseWriterState struct {
wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
sentHeader bool // have we sent the header frame?
handlerDone bool // handler has finished
+ dirty bool // a Write failed; don't reuse this responseWriterState
sentContentLen int64 // non-zero if handler set a Content-Length header
wroteBytes int64
@@ -6027,6 +6028,7 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
date: date,
})
if err != nil {
+ rws.dirty = true
return 0, err
}
if endStream {
@@ -6048,6 +6050,7 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
if len(p) > 0 || endStream {
// only send a 0 byte DATA frame if we're ending the stream.
if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+ rws.dirty = true
return 0, err
}
}
@@ -6059,6 +6062,9 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
trailers: rws.trailers,
endStream: true,
})
+ if err != nil {
+ rws.dirty = true
+ }
return len(p), err
}
return len(p), nil
@@ -6198,7 +6204,7 @@ func http2cloneHeader(h Header) Header {
//
// * Handler calls w.Write or w.WriteString ->
// * -> rws.bw (*bufio.Writer) ->
-// * (Handler migth call Flush)
+// * (Handler might call Flush)
// * -> chunkWriter{rws}
// * -> responseWriterState.writeChunk(p []byte)
// * -> responseWriterState.writeChunk (most of the magic; see comment there)
@@ -6237,10 +6243,19 @@ func (w *http2responseWriter) write(lenData int, dataB []byte, dataS string) (n
func (w *http2responseWriter) handlerDone() {
rws := w.rws
+ dirty := rws.dirty
rws.handlerDone = true
w.Flush()
w.rws = nil
- http2responseWriterStatePool.Put(rws)
+ if !dirty {
+ // Only recycle the pool if all prior Write calls to
+ // the serverConn goroutine completed successfully. If
+ // they returned earlier due to resets from the peer
+ // there might still be write goroutines outstanding
+ // from the serverConn referencing the rws memory. See
+ // issue 20704.
+ http2responseWriterStatePool.Put(rws)
+ }
}
// Push errors.