I continue to hunt a stream accounting bug in either the Go HTTP/2 transport and/or server. Reading code again now, I noticed:
(*serverConn).processHeaders does:
st := sc.newStream(id, 0, initialState)
... where that newStream call is what's responsible for incrementing the stream count:
(that's what's ultimately causing the return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol)) I'm hitting)
But just after that newStream call are two error exit paths:
st := sc.newStream(id, 0, initialState)
if f.HasPriority() {
if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
return err
}
sc.writeSched.AdjustStream(st.id, f.Priority)
}
rw, req, err := sc.newWriterAndRequest(st, f)
if err != nil {
return err
}
// ... [no returns]
go sc.runHandler(rw, req, handler)
return nil
Those two return err errors are suspect. If those happen, then curClientStreams can be left incremented, never to be decremented again.
The decrement happens in (*serverConn).closeStream, which is called from:
processResetStream, reading a RSTStream frame from the client (e.g. they canceled the request)
wroteFrame, called after a frame write is successful, including handler panics. But if we return err above before starting the handler, we can't ever write anything, as the handler never runs.
I'm not sure whether this is what we're hitting yet, but it looks suspicious.
/cc @neild
I continue to hunt a stream accounting bug in either the Go HTTP/2 transport and/or server. Reading code again now, I noticed:
(*serverConn).processHeadersdoes:... where that
newStreamcall is what's responsible for incrementing the stream count:(that's what's ultimately causing the
return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))I'm hitting)But just after that
newStreamcall are two error exit paths:Those two
return errerrors are suspect. If those happen, thencurClientStreamscan be left incremented, never to be decremented again.The decrement happens in
(*serverConn).closeStream, which is called from:processResetStream, reading a RSTStream frame from the client (e.g. they canceled the request)wroteFrame, called after a frame write is successful, including handler panics. But if wereturn errabove before starting the handler, we can't ever write anything, as the handler never runs.I'm not sure whether this is what we're hitting yet, but it looks suspicious.
/cc @neild