From d06997df355a02098d0f30f9c27a5ce184a6277a Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sun, 12 Jan 2014 22:04:22 +0100 Subject: [PATCH] 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. --- django/apps/registry.py | 13 ++++++++----- django/utils/module_loading.py | 13 ------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/django/apps/registry.py b/django/apps/registry.py index a0cd5e0abf..fcd5f576e6 100644 --- a/django/apps/registry.py +++ b/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 diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py index bd012cd55b..a6fe7aebcb 100644 --- a/django/utils/module_loading.py +++ b/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