Fix inappropriate logic in memcachedlock.release()

Whether 'was_deleted' was 'TRUE' or not, eventually we have to remove
self from '_acquired_locks'.
For example:
1. App #1 with coordinator 'A' wants to release lock "b"
2. 'self.coord.client.delete()' failed for some reason(.e.g,
BrokenPipeError,MemcacheUnexpectedCloseError)
3. According to the former logic,lock "b" will not remove
from "_acquired_locks", so "self.heartbeat()" will make it alive
forever until App #1 was down or lock "b" turned expired.
4. Now App #1 with coordinator 'A' wants to acquire lock "c", who
have the same lock-name with lock "b",It is clear that this will
fail and prevent the locked program from continuing to execute.

Change-Id: I6fc33b8e0a88510027bcfc30d1504489d2a91b4e
This commit is contained in:
zhen 2022-05-20 15:57:53 +08:00
parent b21c20f79f
commit c4fc1be88b
1 changed files with 19 additions and 3 deletions

View File

@ -152,10 +152,26 @@ class MemcachedLock(locking.Lock):
if value != self.coord._member_id:
return False
else:
was_deleted = self.coord.client.delete(self.name, noreply=False)
if was_deleted:
# NOTE(zhen): Whether 'was_deleted' was 'TRUE' or not,
# eventually we have to remove self from '_acquired_locks'.
#
# For example:
# 1. App #1 with coordinator 'A' wants to release lock "b"
# 2. 'self.coord.client.delete()' failed for some reason(.e.g,
# BrokenPipeError,MemcacheUnexpectedCloseError)
# 3. According to the former logic,lock "b" will not remove
# from "_acquired_locks", so "self.heartbeat()" will make it alive
# forever until App #1 was down or lock "b" turned expired.
# 4. Now App #1 with coordinator 'A' wants to acquire lock "c",
# who have the same lock-name with lock "b",It is clear that
# this will fail and prevent the locked program from continuing
# to execute.
try:
was_deleted = self.coord.client.delete(self.name,
noreply=False)
finally:
self.coord._acquired_locks.remove(self)
return was_deleted
return was_deleted
@_translate_failures
def heartbeat(self):