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 <@>
This commit is contained in:
greatroar 2020-04-04 21:20:25 +02:00 committed by GitHub
parent 7505ea79a0
commit b7ba401c0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 5 additions and 6 deletions

View File

@ -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()
}