diff --git a/cmd/rate-limit-handler.go b/cmd/rate-limit-handler.go index 3fc371a4a..8c105332d 100644 --- a/cmd/rate-limit-handler.go +++ b/cmd/rate-limit-handler.go @@ -37,8 +37,11 @@ type rateLimit struct { // channel this is in-turn used to rate limit incoming connections in // ServeHTTP() http.Handler method. func (c *rateLimit) acquire() error { + //lock access to enter waitQueue + c.lock.Lock() // Kick out clients when it is really crowded if len(c.waitQueue) == cap(c.waitQueue) { + defer c.lock.Unlock() //unlock after return return errTooManyRequests } @@ -46,11 +49,15 @@ func (c *rateLimit) acquire() error { // wanting to process their requests c.waitQueue <- struct{}{} - // Moving from wait to work queue is protected by a mutex - // to avoid draining waitQueue with multiple simultaneous clients. - c.lock.Lock() - c.workQueue <- <-c.waitQueue + // Unlock now. If we unlock before sending to the waitQueue + // channel, we can have multiple go-routines blocked on + // sending to the waitQueue (and exceeding the max. number of + // waiting connections.) c.lock.Unlock() + + // Block to put a waiting go-routine into processing mode. + c.workQueue <- <-c.waitQueue + return nil }