]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: update bundled http2
authorBrad Fitzpatrick <bradfitz@golang.org>
Mon, 19 Jun 2017 22:59:56 +0000 (22:59 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Mon, 19 Jun 2017 23:26:32 +0000 (23:26 +0000)
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>

src/net/http/h2_bundle.go

index 0533f56f0e067ef2aa9db5a577cb1b0e6f4f0f6d..9ef24ab6cc559297198bae465c164ad63b8293c6 100644 (file)
@@ -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.