• 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
Name
Last commit
Last update
bpf Loading commit data...
context Loading commit data...
dict Loading commit data...
html Loading commit data...
http2 Loading commit data...
icmp Loading commit data...
idna Loading commit data...
internal Loading commit data...
ipv4 Loading commit data...
ipv6 Loading commit data...
lex/httplex Loading commit data...
lif Loading commit data...
nettest Loading commit data...
netutil Loading commit data...
proxy Loading commit data...
publicsuffix Loading commit data...
route Loading commit data...
trace Loading commit data...
webdav Loading commit data...
websocket Loading commit data...
xsrftoken Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
AUTHORS Loading commit data...
CONTRIBUTING.md Loading commit data...
CONTRIBUTORS Loading commit data...
LICENSE Loading commit data...
PATENTS Loading commit data...
README Loading commit data...
codereview.cfg Loading commit data...