From: Brad Fitzpatrick Date: Mon, 19 Jun 2017 22:59:56 +0000 (+0000) Subject: net/http: update bundled http2 X-Git-Tag: go1.9beta2~49 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=be855e3f28507dd3e34eb4699c84493eeaae68db;p=gostls13.git 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 Run-TryBot: Tom Bergan Reviewed-by: Tom Bergan TryBot-Result: Gobot Gobot --- 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.