1
0
mirror of https://github.com/golang/go synced 2024-11-26 14:46:47 -07:00

net/http: clear reference to the request context after transport getConn

Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled.

Updates #50798
This commit is contained in:
Alexander Yastrebov 2023-07-22 13:26:24 +02:00
parent 862fa6d099
commit fd6c83ab07

View File

@ -1205,7 +1205,6 @@ func (t *Transport) dial(ctx context.Context, network, addr string) (net.Conn, e
type wantConn struct {
cm connectMethod
key connectMethodKey // cm.key()
ctx context.Context // context for dial
ready chan struct{} // closed when pc, err pair is delivered
// hooks for testing to know when dials are done
@ -1214,7 +1213,8 @@ type wantConn struct {
beforeDial func()
afterDial func()
mu sync.Mutex // protects pc, err, close(ready)
mu sync.Mutex // protects ctx, pc, err, close(ready)
ctx context.Context // context for dial, cleared after delivered or canceled
pc *persistConn
err error
}
@ -1229,6 +1229,13 @@ func (w *wantConn) waiting() bool {
}
}
// getCtxForDial returns context for dial or nil if connection was delivered or canceled.
func (w *wantConn) getCtxForDial() context.Context {
w.mu.Lock()
defer w.mu.Unlock()
return w.ctx
}
// tryDeliver attempts to deliver pc, err to w and reports whether it succeeded.
func (w *wantConn) tryDeliver(pc *persistConn, err error) bool {
w.mu.Lock()
@ -1238,6 +1245,7 @@ func (w *wantConn) tryDeliver(pc *persistConn, err error) bool {
return false
}
w.ctx = nil
w.pc = pc
w.err = err
if w.pc == nil && w.err == nil {
@ -1255,6 +1263,7 @@ func (w *wantConn) cancel(t *Transport, err error) {
close(w.ready) // catch misbehavior in future delivery
}
pc := w.pc
w.ctx = nil
w.pc = nil
w.err = err
w.mu.Unlock()
@ -1463,8 +1472,12 @@ func (t *Transport) queueForDial(w *wantConn) {
// If the dial is canceled or unsuccessful, dialConnFor decrements t.connCount[w.cm.key()].
func (t *Transport) dialConnFor(w *wantConn) {
defer w.afterDial()
ctx := w.getCtxForDial()
if ctx == nil {
return
}
pc, err := t.dialConn(w.ctx, w.cm)
pc, err := t.dialConn(ctx, w.cm)
delivered := w.tryDeliver(pc, err)
if err == nil && (!delivered || pc.alt != nil) {
// pconn was not passed to w,