summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Tao <daniel.tao@gmail.com>2017-09-22 07:43:00 -0500
committerTim Graham <timograham@gmail.com>2017-09-22 10:16:05 -0400
commit6f7279c4b1db894eb431c182ea9df5d665b3f726 (patch)
treeadb34dd82041ec1f886fde5dbf7b96099ea81e29
parent771e06af2aacff5d544c3004fa6548749ed81a2a (diff)
Refs #28593 -- Made URLResolver._populate() more resilient to signal interrupts.
_populate() sets the populating attribute to prevent infinite recursion in case a urlconf includes itself. The flag is a threadlocal to avoid a race condition [1] where one thread sets the flag and another checks it, then proceeds to access data that's supposed to be populated (e.g. _reverse_dict) but isn't yet. The potential still exists for a thread to set the threadlocal, then be interrupted by a signal such as SIGALRM and raise before resetting the threadlocal flag. In this scenario, subsequent calls to _populate() in the same thread will short-circuit erroneously. The bulk of the method was already wrapped in a try/finally in df41b5a, but since a signal interrupt can occur at any line executed by the interpreter, this moves up the try to ensure threadlocal gets reset. [1]: https://groups.google.com/d/msg/django-developers/D_bIeinKHjE/4NmVQUJqAgAJ
-rw-r--r--django/urls/resolvers.py10
1 files changed, 5 insertions, 5 deletions
diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py
index f91e821b38..9ee96d38d1 100644
--- a/django/urls/resolvers.py
+++ b/django/urls/resolvers.py
@@ -398,12 +398,12 @@ class URLResolver:
# thread-local variable.
if getattr(self._local, 'populating', False):
return
- self._local.populating = True
- lookups = MultiValueDict()
- namespaces = {}
- apps = {}
- language_code = get_language()
try:
+ self._local.populating = True
+ lookups = MultiValueDict()
+ namespaces = {}
+ apps = {}
+ language_code = get_language()
for url_pattern in reversed(self.url_patterns):
p_pattern = url_pattern.pattern.regex.pattern
if p_pattern.startswith('^'):