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.
This commit is contained in:
Aymeric Augustin 2014-01-12 22:04:22 +01:00 committed by Anssi Kääriäinen
parent 3777390713
commit d06997df35
2 changed files with 8 additions and 18 deletions

View File

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

View File

@ -1,6 +1,5 @@
from __future__ import absolute_import # Avoid importing `importlib` from this package. from __future__ import absolute_import # Avoid importing `importlib` from this package.
from contextlib import contextmanager
import copy import copy
import imp import imp
from importlib import import_module from importlib import import_module
@ -36,18 +35,6 @@ def import_by_path(dotted_path, error_prefix=''):
return attr 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): def autodiscover_modules(*args, **kwargs):
""" """
Auto-discover INSTALLED_APPS modules and fail silently when Auto-discover INSTALLED_APPS modules and fail silently when