From 5039c6f01d0bd1f58f950e80cddf7472444a70a4 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 16 May 2019 11:26:04 -0400 Subject: Mutex the declarative scan/map process against configure_mappers() Applied the mapper "configure mutex" against the declarative class mapping process, to guard against the race which can occur if mappers are used while dynamic module import schemes are still in the process of configuring mappers for related classes. This does not guard against all possible race conditions, such as if the concurrent import has not yet encountered the dependent classes as of yet, however it guards against as much as possible within the SQLAlchemy declarative process. Fixes: #4686 Change-Id: I0349036b8078bd42265ab40862cfbfe5bf9d5b44 --- lib/sqlalchemy/ext/declarative/base.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'lib/sqlalchemy/ext') diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index 62db282d1..622a83736 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -17,6 +17,7 @@ from ... import util from ...orm import class_mapper from ...orm import exc as orm_exc from ...orm import mapper +from ...orm import mapperlib from ...orm import synonym from ...orm.attributes import QueryableAttribute from ...orm.base import _is_mapped_class @@ -155,6 +156,7 @@ class _MapperConfig(object): cfg_cls = _DeferredMapperConfig else: cfg_cls = _MapperConfig + cfg_cls(cls_, classname, dict_) def __init__(self, cls_, classname, dict_): @@ -177,17 +179,21 @@ class _MapperConfig(object): self._scan_attributes() - clsregistry.add_class(self.classname, self.cls) + mapperlib._CONFIGURE_MUTEX.acquire() + try: + clsregistry.add_class(self.classname, self.cls) - self._extract_mappable_attributes() + self._extract_mappable_attributes() - self._extract_declared_columns() + self._extract_declared_columns() - self._setup_table() + self._setup_table() - self._setup_inheritance() + self._setup_inheritance() - self._early_mapping() + self._early_mapping() + finally: + mapperlib._CONFIGURE_MUTEX.release() def _early_mapping(self): self.map() -- cgit v1.2.1