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
This commit is contained in:
parent
771e06af2a
commit
6f7279c4b1
|
@ -398,12 +398,12 @@ class URLResolver:
|
||||||
# thread-local variable.
|
# thread-local variable.
|
||||||
if getattr(self._local, 'populating', False):
|
if getattr(self._local, 'populating', False):
|
||||||
return
|
return
|
||||||
|
try:
|
||||||
self._local.populating = True
|
self._local.populating = True
|
||||||
lookups = MultiValueDict()
|
lookups = MultiValueDict()
|
||||||
namespaces = {}
|
namespaces = {}
|
||||||
apps = {}
|
apps = {}
|
||||||
language_code = get_language()
|
language_code = get_language()
|
||||||
try:
|
|
||||||
for url_pattern in reversed(self.url_patterns):
|
for url_pattern in reversed(self.url_patterns):
|
||||||
p_pattern = url_pattern.pattern.regex.pattern
|
p_pattern = url_pattern.pattern.regex.pattern
|
||||||
if p_pattern.startswith('^'):
|
if p_pattern.startswith('^'):
|
||||||
|
|
Loading…
Reference in New Issue