http2: cancel handler context on stream errors

When we reset a stream due to an error, cancel the handler context.

Fixes golang/go#67036

Change-Id: I66941d9bffb35d8b4358ff8d85cc784c1846afa6
Reviewed-on: https://go-review.googlesource.com/c/net/+/585595
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Damien Neil
2024-05-13 10:46:16 -07:00
parent 2c14f519f3
commit 8aa6dbf491
2 changed files with 37 additions and 0 deletions

View File

@@ -1661,6 +1661,7 @@ func (sc *serverConn) closeStream(st *stream, err error) {
}
}
st.closeErr = err
st.cancelCtx()
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
sc.writeSched.CloseStream(st.id)
}

View File

@@ -4900,3 +4900,39 @@ func TestServerUpgradeRequestPrefaceFailure(t *testing.T) {
c2.Close()
<-donec
}
// Issue 67036: A stream error should result in the handler's request context being canceled.
func TestServerRequestCancelOnError(t *testing.T) {
recvc := make(chan struct{}) // handler has started
donec := make(chan struct{}) // handler has finished
st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
close(recvc)
<-r.Context().Done()
close(donec)
})
defer st.Close()
st.writePreface()
st.writeInitialSettings()
st.writeSettingsAck()
// Client sends request headers, handler starts.
st.writeHeaders(HeadersFrameParam{
StreamID: 1,
BlockFragment: st.encodeHeader(),
EndStream: true,
EndHeaders: true,
})
<-recvc
// Client sends an invalid second set of request headers.
// The stream is reset.
// The handler's context is canceled, and the handler exits.
st.writeHeaders(HeadersFrameParam{
StreamID: 1,
BlockFragment: st.encodeHeader(),
EndStream: true,
EndHeaders: true,
})
<-donec
}