summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Harlow <harlowja@yahoo-inc.com>2015-04-15 16:21:24 -0700
committerJoshua Harlow <harlowja@yahoo-inc.com>2015-04-15 16:22:35 -0700
commit3fd7065a18bdb911c0693083d968a3771ce4cad6 (patch)
tree87434fd2c0f236823d632b0c992d9327f2664285
parentdfe509bd256e4ec3e6d487e230abd8169655bc40 (diff)
downloadpymemcache-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.py24
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()