Skip to content

Commit 019f74e

Browse files
committed
recipe(lock): retry lock cleanup
If a non-blocking lock fails to acquire the lock, and then encounters a KazooError (due to a suspended session), the _best_effort_cleanup method will swallow the exception and control will return without the lock contender node being deleted. If the session resumes (does not expire) then we will have left a lock contender in place, which will eventually become an orphaned, stuck lock once the original actor releases it. To correct this, retry deleting the lock contender in all cases. Due to the importance of this, we ignore the supplied timeout (in case the aquire method was called with a timeout) and retry forever. Closes: #732
1 parent c5ab988 commit 019f74e

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

kazoo/recipe/lock.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,13 +193,13 @@ def acquire(self, blocking=True, timeout=None, ephemeral=True):
193193
except KazooException:
194194
# if we did ultimately fail, attempt to clean up
195195
if not already_acquired:
196-
self._best_effort_cleanup()
196+
self._cleanup()
197197
self.cancelled = False
198198
raise
199199
if gotten:
200200
self.is_acquired = gotten
201201
if not gotten and not already_acquired:
202-
self._best_effort_cleanup()
202+
self._cleanup()
203203
return gotten
204204
finally:
205205
self._acquire_method_lock.release()
@@ -318,13 +318,18 @@ def _find_node(self):
318318
def _delete_node(self, node):
319319
self.client.delete(self.path + "/" + node)
320320

321-
def _best_effort_cleanup(self):
322-
try:
323-
node = self.node or self._find_node()
324-
if node:
321+
def _cleanup(self):
322+
self._retry(
323+
self._inner_cleanup,
324+
)
325+
326+
def _inner_cleanup(self):
327+
node = self.node or self._find_node()
328+
if node:
329+
try:
325330
self._delete_node(node)
326-
except KazooException: # pragma: nocover
327-
pass
331+
except NoNodeError: # pragma: nocover
332+
pass
328333

329334
def release(self):
330335
"""Release the lock immediately."""

0 commit comments

Comments
 (0)