Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #18251 -- Removed a deadlock possibility in apploading

Thanks to harm for the report and comments.
  • Loading branch information...
commit 4073dd4170ee736565a951121e8c01cb3db8d477 1 parent 3673795
@akaariai akaariai authored
Showing with 11 additions and 6 deletions.
  1. +11 −6 django/db/models/loading.py
View
17 django/db/models/loading.py
@@ -6,9 +6,9 @@
from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule
+import imp
import sys
import os
-import threading
__all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
'load_app', 'app_cache_ready')
@@ -39,7 +39,6 @@ class AppCache(object):
handled = {},
postponed = [],
nesting_level = 0,
- write_lock = threading.RLock(),
_get_models_cache = {},
)
@@ -54,7 +53,13 @@ def _populate(self):
"""
if self.loaded:
return
- self.write_lock.acquire()
+ # Note that we want to use the import lock here - the app loading is
+ # in many cases initiated implicitly by importing, and thus it is
+ # possible to end up in deadlock when one thread initiates loading
+ # without holding the importer lock and another thread then tries to
+ # import something which also lauches the app loading. For details of
+ # this situation see #18251.
+ imp.acquire_lock()
try:
if self.loaded:
return
@@ -67,7 +72,7 @@ def _populate(self):
self.load_app(app_name)
self.loaded = True
finally:
- self.write_lock.release()
+ imp.release_lock()
def _label_for(self, app_mod):
"""
@@ -138,7 +143,7 @@ def get_app(self, app_label, emptyOK=False):
the app has no models in it and 'emptyOK' is True, returns None.
"""
self._populate()
- self.write_lock.acquire()
+ imp.acquire_lock()
try:
for app_name in settings.INSTALLED_APPS:
if app_label == app_name.split('.')[-1]:
@@ -151,7 +156,7 @@ def get_app(self, app_label, emptyOK=False):
return mod
raise ImproperlyConfigured("App with label %s could not be found" % app_label)
finally:
- self.write_lock.release()
+ imp.release_lock()
def get_app_errors(self):
"Returns the map of known problems with the INSTALLED_APPS."
Please sign in to comment.
Something went wrong with that request. Please try again.