Skip to content

Commit

Permalink
Fix clientGetURLDeadline
Browse files Browse the repository at this point in the history
Based on #962
Make sure req is always released and fix a race condition.
  • Loading branch information
erikdubbelboer committed Feb 7, 2021
1 parent 0956208 commit 1494fdc
Showing 1 changed file with 35 additions and 14 deletions.
49 changes: 35 additions & 14 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -856,38 +856,63 @@ func clientGetURLDeadline(dst []byte, url string, deadline time.Time, c clientDo
}
ch = chv.(chan clientURLResponse)

req := AcquireRequest()

// Note that the request continues execution on ErrTimeout until
// client-specific ReadTimeout exceeds. This helps limiting load
// on slow hosts by MaxConns* concurrent requests.
//
// Without this 'hack' the load on slow host could exceed MaxConns*
// concurrent requests, since timed out requests on client side
// usually continue execution on the host.

var mu sync.Mutex
var timedout, responded bool

go func() {
req := AcquireRequest()

statusCodeCopy, bodyCopy, errCopy := doRequestFollowRedirectsBuffer(req, dst, url, c)
ch <- clientURLResponse{
statusCode: statusCodeCopy,
body: bodyCopy,
err: errCopy,
mu.Lock()
{
if !timedout {
ch <- clientURLResponse{
statusCode: statusCodeCopy,
body: bodyCopy,
err: errCopy,
}
responded = true
}
}
mu.Unlock()

ReleaseRequest(req)
}()

tc := AcquireTimer(timeout)
select {
case resp := <-ch:
ReleaseRequest(req)
clientURLResponseChPool.Put(chv)
statusCode = resp.statusCode
body = resp.body
err = resp.err
case <-tc.C:
body = dst
err = ErrTimeout
mu.Lock()
{
if responded {
resp := <-ch
statusCode = resp.statusCode
body = resp.body
err = resp.err
} else {
timedout = true
err = ErrTimeout
body = dst
}
}
mu.Unlock()
}
ReleaseTimer(tc)

clientURLResponseChPool.Put(chv)

return statusCode, body, err
}

Expand Down Expand Up @@ -1193,10 +1218,6 @@ func clientDoDeadline(req *Request, resp *Response, deadline time.Time, c client
}
ReleaseTimer(tc)

select {
case <-ch:
default:
}
errorChPool.Put(chv)

return err
Expand Down

0 comments on commit 1494fdc

Please sign in to comment.