redis: fix concurrent access on acquire()

Redis-py is not thread safe and in lock management, which means the following
can also happen:
1. lock.acquire()
2a. lock.release() ---\_ at the same time for all 2. operations
2b. lock.acquire() ---/
2c. lock.heartbeat() /

which means the lock can be when a lock is already acquired and in the process
of being released and re-acquired in paralllel:
1. acquire() acquire the lock (self._lock.acquire())
2. release() release the lock (self._lock.release()) and remove it from
   self._lock.acquire() where it's not (discard() does not raise on non-existing
   element)
3. acquire() put the lock in _acquired_locks
4. heartbeat() iterates on _acquired_locks and try to extend a lock that indeed
   was acquired but was in the mean time released by Redis.

Change-Id: Ib9549b44485cb15de312ec9dfa57b148cb45e2c9
Closes-Bug: #1557593
This commit is contained in:
Julien Danjou 2017-03-18 10:33:57 +01:00
parent 54496ff820
commit 059f2ae540
1 changed files with 2 additions and 1 deletions

View File

@ -86,7 +86,8 @@ class RedisLock(locking.Lock):
acquired = self._lock.acquire(
blocking=blocking, blocking_timeout=timeout)
if acquired:
self._coord._acquired_locks.add(self)
with self._exclusive_access:
self._coord._acquired_locks.add(self)
return acquired
def release(self):