]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Prevent deadlock in LRUCache.setdefault
authorEtiennePelletier <etpelletier93@hotmail.com>
Thu, 9 May 2019 20:47:54 +0000 (16:47 -0400)
committerDavid Lord <davidism@gmail.com>
Fri, 4 Oct 2019 14:58:58 +0000 (07:58 -0700)
setdefault was acquiring write_lock, then calling getitem and also
potentially setitem, which also both try to acquire the write lock.

CHANGES.rst
jinja2/utils.py

index efcd2e298f6c0375b2b779ed6c528d2348a294a7..bf4ac1418987975e0c0826a9cca10cb35d41f332 100644 (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
index 2e0aec2229729ed029a24e4d02fb800aa09c2ca1..9fb2b353f52bcd9c3656fe2afd758c637da4bc07 100644 (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))