From f7c354c760cf6974f0a954eb2e024dceb842f002 Mon Sep 17 00:00:00 2001 From: Erik Dubbelboer Date: Thu, 11 Nov 2021 16:59:56 +0100 Subject: [PATCH] Fix race condition in Client.mCleaner This could result in HostClients being removed that were still in use. --- client.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client.go b/client.go index 5e05e131d4..800cec3a4d 100644 --- a/client.go +++ b/client.go @@ -515,6 +515,10 @@ func (c *Client) Do(req *Request, resp *Response) error { startCleaner = true } } + + atomic.AddInt32(&hc.pendingClientRequests, 1) + defer atomic.AddInt32(&hc.pendingClientRequests, -1) + c.mLock.Unlock() if startCleaner { @@ -553,12 +557,10 @@ func (c *Client) mCleaner(m map[string]*HostClient) { c.mLock.Lock() for k, v := range m { v.connsLock.Lock() - shouldRemove := v.connsCount == 0 - v.connsLock.Unlock() - - if shouldRemove { + if v.connsCount == 0 && atomic.LoadInt32(&v.pendingClientRequests) == 0 { delete(m, k) } + v.connsLock.Unlock() } if len(m) == 0 { mustStop = true @@ -783,6 +785,10 @@ type HostClient struct { pendingRequests int32 + // pendingClientRequests counts the number of requests that a Client is currently running using this HostClient. + // It will be incremented ealier than pendingRequests and will be used by Client to see if the HostClient is still in use. + pendingClientRequests int32 + connsCleanerRun bool }