• Tom Bergan's avatar
    http2: don't flush a stream's write queue in sc.resetStream · 3d9a20a7
    Tom Bergan authored
    resetStream(st) queues a RST_STREAM frame and then calls closeStream(st).
    Unfortunately, closeStream(st) flushes any writes pending on st, which
    can drop the RST_STREAM that was just queued. (If we are lucky, the
    RST_STREAM will fit in the send buffer and won't be dropped, however,
    if we are unlucky the RST_STREAM will be dropped.)
    
    I fixed this bug by removing closeStream(st) from resetStream. Instead,
    closeStream happens after the RST_STREAM frame is written. This is a more
    direct implementation of the diagram in RFC 7540 Section 5.1, which says
    that a stream does not transition to "closed" until after the RST_STREAM
    has been sent.
    
    A side-effect is that the stream may stay open for longer than it did
    previously (since it won't close until *after* the RST_STREAM frame is
    actually written). Situations like the following are a problem:
    
    - Client sends a DATA frame that exceeds its flow-control window
    - Server returns streamError(ErrCodeFlowControl) from processData
    - RST_STREAM is queued behind other frames
    - Server process the request body and releases flow-control
    - Client sends another DATA frame, this one fits in the flow-control
      window. Server should NOT process this frame.
    
    To avoid the above problem, we set a bool st.resetQueued=true when
    RST_STREAM is queued, then ignore all future incoming HEADERS and DATA
    frames on that stream.
    
    I also removed st.sentReset and st.gotReset, which were used to ignore
    frames after RST_STREAM is sent. Now we just check if the stream is closed.
    
    Fixes golang/go#18111
    
    Change-Id: Ieb7c848989431add5b7d95f40d6d91db7edc4980
    Reviewed-on: https://go-review.googlesource.com/34238Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    3d9a20a7
server_test.go 98.8 KB