Skip to content

Commit 37bcda3

Browse files
kulallwangStephenSorriaux
authored andcommitted
fix(recipe): No more memory leak when ChildrenWatch was stopped (#543)
This ensures that the watcher is removed from the client listener when the func given to ChildrenWatch returns False. Previously, the watcher was never removed so the ChildrenWatch object would endlessly grow in memory. A unit test is added to ensure this case never happen again. Fix #542
1 parent 2ae392e commit 37bcda3

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

kazoo/recipe/watchers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ def _get_children(self, event=None):
341341
if result is False:
342342
self._stopped = True
343343
self._func = None
344+
if self._allow_session_lost:
345+
self._client.remove_listener(self._session_watcher)
344346
except Exception as exc:
345347
log.exception(exc)
346348
raise

kazoo/tests/test_watchers.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,40 @@ def changed(children):
418418
update.wait(0.5)
419419
eq_(all_children, ['smith'])
420420

421+
def test_child_watcher_remove_session_watcher(self):
422+
update = threading.Event()
423+
all_children = ['fred']
424+
425+
fail_through = []
426+
427+
def changed(children):
428+
while all_children:
429+
all_children.pop()
430+
all_children.extend(children)
431+
update.set()
432+
if fail_through:
433+
return False
434+
435+
children_watch = self.client.ChildrenWatch(self.path, changed)
436+
session_watcher = children_watch._session_watcher
437+
438+
update.wait(10)
439+
eq_(session_watcher in self.client.state_listeners, True)
440+
eq_(all_children, [])
441+
update.clear()
442+
443+
fail_through.append(True)
444+
self.client.create(self.path + '/' + 'smith')
445+
update.wait(10)
446+
eq_(session_watcher not in self.client.state_listeners, True)
447+
eq_(all_children, ['smith'])
448+
update.clear()
449+
450+
self.client.create(self.path + '/' + 'george')
451+
update.wait(10)
452+
eq_(session_watcher not in self.client.state_listeners, True)
453+
eq_(all_children, ['smith'])
454+
421455
def test_child_watch_session_loss(self):
422456
update = threading.Event()
423457
all_children = ['fred']

0 commit comments

Comments
 (0)