Skip to content

Commit

Permalink
net/http: clear reference to the request context after transport getConn
Browse files Browse the repository at this point in the history
Clears wannConn ctx and prevents pending dialConnFor after connection delivered or canceled.

Fixes #50798
  • Loading branch information
AlexanderYastrebov committed Jul 22, 2023
1 parent 2eca0b1 commit e17d3af
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/net/http/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand All @@ -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()
Expand All @@ -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 {
Expand All @@ -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()
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit e17d3af

Please sign in to comment.