diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py index 9d3379a821..5b722474c9 100644 --- a/django/urls/resolvers.py +++ b/django/urls/resolvers.py @@ -381,6 +381,7 @@ class URLResolver: self._callback_strs = set() self._populated = False self._local = threading.local() + self._urlconf_lock = threading.Lock() def __repr__(self): if isinstance(self.urlconf_name, list) and self.urlconf_name: @@ -568,10 +569,14 @@ class URLResolver: @cached_property def urlconf_module(self): - if isinstance(self.urlconf_name, str): - return import_module(self.urlconf_name) - else: - return self.urlconf_name + # import_module is not thread safe if the module throws an exception + # during import, and can return an empty module object in Python < 3.6 + # (see https://bugs.python.org/issue36284). + with self._urlconf_lock: + if isinstance(self.urlconf_name, str): + return import_module(self.urlconf_name) + else: + return self.urlconf_name @cached_property def url_patterns(self): diff --git a/docs/releases/2.2.5.txt b/docs/releases/2.2.5.txt index 9f143c8d96..592b8256a1 100644 --- a/docs/releases/2.2.5.txt +++ b/docs/releases/2.2.5.txt @@ -22,3 +22,6 @@ Bugfixes :attr:`ModelAdmin.list_filter ` choices to foreign objects don't respect a model's ``Meta.ordering`` (:ticket:`30449`). + +* Fixed a race condition in loading URLconf module that could cause a crash of + auto-reloader on Python 3.5 and below (:ticket:`30500`).