diff options
author | Joshua Harlow <harlowja@yahoo-inc.com> | 2015-04-15 16:21:24 -0700 |
---|---|---|
committer | Joshua Harlow <harlowja@yahoo-inc.com> | 2015-04-15 16:22:35 -0700 |
commit | 3fd7065a18bdb911c0693083d968a3771ce4cad6 (patch) | |
tree | 87434fd2c0f236823d632b0c992d9327f2664285 | |
parent | dfe509bd256e4ec3e6d487e230abd8169655bc40 (diff) | |
download | pymemcache-3fd7065a18bdb911c0693083d968a3771ce4cad6.tar.gz |
Run 'after_remove' callback outside of lock
Avoid holding the pool lock while calling into
the 'after_remove' callback to ensure that no kind
of deadlock is likely to occur (say if the callback
calls back into the pool).
-rw-r--r-- | pymemcache/pool.py | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/pymemcache/pool.py b/pymemcache/pool.py index 73528de..c341ceb 100644 --- a/pymemcache/pool.py +++ b/pymemcache/pool.py @@ -74,14 +74,16 @@ class ObjectPool(object): return obj def destroy(self, obj, silent=True): + was_dropped = False with self._lock: try: self._used_objs.remove(obj) - if self._after_remove is not None: - self._after_remove(obj) + was_dropped = True except ValueError: if not silent: raise + if was_dropped and self._after_remove is not None: + self._after_remove(obj) def release(self, obj, silent=True): with self._lock: @@ -93,12 +95,16 @@ class ObjectPool(object): raise def clear(self): - with self._lock: - if self._after_remove is not None: - while self._used_objs: - self._after_remove(self._used_objs.pop()) - while self._free_objs: - self._after_remove(self._free_objs.pop()) - else: + if self._after_remove is not None: + needs_destroy = [] + with self._lock: + needs_destroy.extend(self._used_objs) + needs_destroy.extend(self._free_objs) + self._free_objs.clear() + self._used_objs.clear() + for obj in needs_destroy: + self._after_remove(obj) + else: + with self._lock: self._free_objs.clear() self._used_objs.clear() |