Gitlab::Redis.with is not thread-safe
This method is currently implemented as follows:
def with
if @pool.nil?
POOL_MUTEX.synchronize do
@pool = ConnectionPool.new { ::Redis.new(params) }
end
end
@pool.with { |redis| yield redis }
end
While this will work on MRI this won't work on a Ruby without a GIL. When two threads first reach this method in parallel the expression if @pool.nil?
may evaluate to true
for both threads at the same time. This would result in both attempting to acquire the lock (which will succeed, though not in parallel) and then both creating a new ConnectionPool
. Probably the easiest way to solve this is to use @pool ||= ConnectionPool.new ...
instead of just using the =
operator. This is safe because at this point the lock is acquired by only a single thread.