Moves swapState up, so it gets executed no matter what. (#2649)
* Moves swapState up, so it gets executed no matter what. * Adds an explanation.
This commit is contained in:
@ -1030,6 +1030,9 @@ func (t *http2Server) deleteStream(s *Stream, eosReceived bool) {
|
|||||||
// closeStream clears the footprint of a stream when the stream is not needed
|
// closeStream clears the footprint of a stream when the stream is not needed
|
||||||
// any more.
|
// any more.
|
||||||
func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) {
|
func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) {
|
||||||
|
// Mark the stream as done
|
||||||
|
oldState := s.swapState(streamDone)
|
||||||
|
|
||||||
// In case stream sending and receiving are invoked in separate
|
// In case stream sending and receiving are invoked in separate
|
||||||
// goroutines (e.g., bi-directional streaming), cancel needs to be
|
// goroutines (e.g., bi-directional streaming), cancel needs to be
|
||||||
// called to interrupt the potential blocking on other goroutines.
|
// called to interrupt the potential blocking on other goroutines.
|
||||||
@ -1051,8 +1054,19 @@ func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, hd
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do the check here, because of the following scenario:
|
||||||
|
// 1. closeStream is called first with a trailer. A trailer item with a piggybacked cleanup item
|
||||||
|
// is put to control buffer.
|
||||||
|
// 2. Loopy writer is waiting on a stream quota. It will never get it because client errored at
|
||||||
|
// some point. So loopy can't act on trailer
|
||||||
|
// 3. Client sends a RST_STREAM due to the error. Then closeStream is called without a trailer as
|
||||||
|
// the result of the received RST_STREAM.
|
||||||
|
// If we do this check at the beginning of the closeStream, then we won't put a cleanup item in
|
||||||
|
// response to received RST_STREAM into the control buffer and outStream in loopy writer will
|
||||||
|
// never get cleaned up.
|
||||||
|
|
||||||
// If the stream is already done, don't send the trailer.
|
// If the stream is already done, don't send the trailer.
|
||||||
if s.swapState(streamDone) == streamDone {
|
if oldState == streamDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user