Prevent deadlock in LRUCache.setdefault

setdefault was acquiring write_lock, then calling getitem and also
potentially setitem, which also both try to acquire the write lock.
This commit is contained in:
EtiennePelletier 2019-05-09 16:47:54 -04:00 committed by David Lord
parent 71133493b5
commit 065b58fc74
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
2 changed files with 6 additions and 10 deletions

View File

@ -21,6 +21,7 @@ Unreleased
2.56e-3. :issue:`912`, :pr:`922`
- Int and float literals can be written with the '_' separator for
legibility, like 12_345. :pr:`923`
- Fix a bug causing deadlocks in ``LRUCache.setdefault``. :pr:`1000`
Version 2.10.2

View File

@ -355,15 +355,11 @@ class LRUCache(object):
"""Set `default` if the key is not in the cache otherwise
leave unchanged. Return the value of this key.
"""
self._wlock.acquire()
try:
try:
return self[key]
except KeyError:
self[key] = default
return default
finally:
self._wlock.release()
return self[key]
except KeyError:
self[key] = default
return default
def clear(self):
"""Clear the cache."""
@ -435,7 +431,6 @@ class LRUCache(object):
try:
self._remove(key)
except ValueError:
# __getitem__ is not locked, it might happen
pass
finally:
self._wlock.release()
@ -479,7 +474,7 @@ class LRUCache(object):
__iter__ = iterkeys
def __reversed__(self):
"""Iterate over the values in the cache dict, oldest items
"""Iterate over the keys in the cache dict, oldest items
coming first.
"""
return iter(tuple(self._queue))