Browse Source

Used a regular lock for app registry population.

Since the app registry is always populated before the first request is
processed, the situation described in #18251 for the old app cache
cannot happen any more.

Refs #18251, #21628.
Aymeric Augustin 11 years ago
parent
commit
d674fe6dee
2 changed files with 8 additions and 18 deletions
  1. 8 5
      django/apps/registry.py
  2. 0 13
      django/utils/module_loading.py

+ 8 - 5
django/apps/registry.py

@@ -1,11 +1,11 @@
 from collections import Counter, defaultdict, OrderedDict
 import os
 import sys
+import threading
 import warnings
 
 from django.core.exceptions import ImproperlyConfigured
 from django.utils import lru_cache
-from django.utils.module_loading import import_lock
 from django.utils._os import upath
 
 from .base import AppConfig
@@ -44,6 +44,9 @@ class Apps(object):
         # Whether the registry is populated.
         self.ready = False
 
+        # Lock for thread-safe population.
+        self._lock = threading.Lock()
+
         # Pending lookups for lazy relations.
         self._pending_lookups = {}
 
@@ -61,10 +64,10 @@ class Apps(object):
         """
         if self.ready:
             return
-        # Since populate() may be a side effect of imports, and since it will
-        # itself import modules, an ABBA deadlock between threads would be
-        # possible if we didn't take the import lock. See #18251.
-        with import_lock():
+
+        # populate() might be called by two threads in parallel on servers
+        # that create threads before initializing the WSGI callable.
+        with self._lock:
             if self.ready:
                 return
 

+ 0 - 13
django/utils/module_loading.py

@@ -1,6 +1,5 @@
 from __future__ import absolute_import  # Avoid importing `importlib` from this package.
 
-from contextlib import contextmanager
 import copy
 import imp
 from importlib import import_module
@@ -36,18 +35,6 @@ def import_by_path(dotted_path, error_prefix=''):
     return attr
 
 
-@contextmanager
-def import_lock():
-    """
-    Context manager that aquires the import lock.
-    """
-    imp.acquire_lock()
-    try:
-        yield
-    finally:
-        imp.release_lock()
-
-
 def autodiscover_modules(*args, **kwargs):
     """
     Auto-discover INSTALLED_APPS modules and fail silently when