From b7ba401c0b9aae91b56337bcd8fe7e5b0837e5d7 Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Sat, 4 Apr 2020 21:20:25 +0200 Subject: [PATCH] cmd/strelaypoolsrv: Fix race condition in caching (#6496) Successful LRU cache lookups modify the cache's recency list, so RWMutex.RLock isn't enough protection. Secondarily, multiple concurrent lookups with the same key should not create separate rate limiters, so release the lock only when presence of the key in the cache has been ascertained. Co-authored-by: greatroar <@> --- cmd/strelaypoolsrv/main.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/strelaypoolsrv/main.go b/cmd/strelaypoolsrv/main.go index 693674080..47e2a8de8 100644 --- a/cmd/strelaypoolsrv/main.go +++ b/cmd/strelaypoolsrv/main.go @@ -116,10 +116,10 @@ var ( requestQueueLen = 10 requestProcessors = 1 - getMut = sync.NewRWMutex() + getMut = sync.NewMutex() getLRUCache *lru.Cache - postMut = sync.NewRWMutex() + postMut = sync.NewMutex() postLRUCache *lru.Cache requests chan request @@ -583,22 +583,21 @@ func evict(relay *relay) func() { } } -func limit(addr string, cache *lru.Cache, lock sync.RWMutex, intv time.Duration, burst int) bool { +func limit(addr string, cache *lru.Cache, lock sync.Mutex, intv time.Duration, burst int) bool { if host, _, err := net.SplitHostPort(addr); err == nil { addr = host } - lock.RLock() + lock.Lock() bkt, ok := cache.Get(addr) - lock.RUnlock() if ok { + lock.Unlock() bkt := bkt.(*rate.Limiter) if !bkt.Allow() { // Rate limit return true } } else { - lock.Lock() cache.Add(addr, rate.NewLimiter(rate.Every(intv), burst)) lock.Unlock() }