From 613c39d390d0672bb2e67c5d2266e07491e88582 Mon Sep 17 00:00:00 2001 From: B Tasker <88340935+btasker@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:23:52 +0100 Subject: [PATCH] net/http2: if the only stream in a connection times out, prevent re-use This commit mitigates some raciness which can occur when an established connection fails. Without it, the connection can continue to be drawn from the connection pool, leading to subsequent requests failing. Fixes golang/go#59690 --- http2/transport.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/http2/transport.go b/http2/transport.go index f965579f7..c577b5def 100644 --- a/http2/transport.go +++ b/http2/transport.go @@ -1444,8 +1444,22 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) { respHeaderRecv = nil respHeaderTimer = nil // keep waiting for END_STREAM case <-cs.abort: + // If this was the only active stream, mark the connection + // as not for re-use in order to address raciness if the caller + // tries to call closeIdleConnections() before the stream has been + // removed + if len(cc.streams) == 1 { + cc.doNotReuse = true + } return cs.abortErr case <-ctx.Done(): + // If this was the only active stream, mark the connection + // as not for re-use in order to address raciness if the caller + // tries to call closeIdleConnections() before the stream has been + // removed + if len(cc.streams) == 1 { + cc.doNotReuse = true + } return ctx.Err() case <-cs.reqCancel: return errRequestCanceled