Skip to content

Commit

Permalink
Lock.release(): reorder code to avoid token overwrite
Browse files Browse the repository at this point in the history
* assignment to self.token was not protected by the lock, so the value could get overwritten
* do_release() now has an expected_token parameter that receives the old token value
* NOTE: this only fixes the issue for locks that do not have timeouts
  • Loading branch information
chillipino committed Jun 5, 2014
1 parent e7589d7 commit 643d76d
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions redis/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,16 @@ def release(self):
"Releases the already acquired lock"
if self.token is None:
raise LockError("Cannot release an unlocked lock")
try:
self.do_release()
finally:
self.token = None
expected_token = self.token
self.token = None
self.do_release(expected_token)

def do_release(self):
def do_release(self, expected_token):
name = self.name
token = self.token

def execute_release(pipe):
lock_value = pipe.get(name)
if lock_value != token:
if lock_value != expected_token:
raise LockError("Cannot release a lock that's no longer owned")
pipe.delete(name)

Expand Down Expand Up @@ -229,9 +227,9 @@ def do_acquire(self, token):
args=[token, timeout],
client=self.redis))

def do_release(self):
def do_release(self, expected_token):
if not bool(self.lua_release(keys=[self.name],
args=[self.token],
args=[expected_token],
client=self.redis)):
raise LockError("Cannot release a lock that's no longer owned")

Expand Down

0 comments on commit 643d76d

Please sign in to comment.