From: Mike Bayer Date: Thu, 25 Sep 2008 15:59:37 +0000 (+0000) Subject: - fixed RLock-related bug in mapper which could deadlock X-Git-Tag: rel_0_5rc2~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a32c1a1e25710468e62d6499f89e4ad26c90f21d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - fixed RLock-related bug in mapper which could deadlock upon reentrant mapper compile() calls, something that occurs when using declarative constructs inside of ForeignKey objects. --- diff --git a/CHANGES b/CHANGES index 35b8a8d28e..5fb8861cb0 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,11 @@ CHANGES is updated/inserted, now honors the insert order of the objects given. + - fixed RLock-related bug in mapper which could deadlock + upon reentrant mapper compile() calls, something that + occurs when using declarative constructs inside of + ForeignKey objects. + - sql - column.in_(someselect) can now be used as a columns-clause expression without the subquery diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 9c8fcf97eb..886fcec91e 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -350,31 +350,33 @@ class Mapper(object): return self _COMPILE_MUTEX.acquire() - global _already_compiling - if _already_compiling: - # re-entrance to compile() occurs rarely, when a class-mapped construct is - # used within a ForeignKey, something that is possible - # when using the declarative layer - self.__initialize_properties() - return - _already_compiling = True try: + global _already_compiling + if _already_compiling: + # re-entrance to compile() occurs rarely, when a class-mapped construct is + # used within a ForeignKey, something that is possible + # when using the declarative layer + self.__initialize_properties() + return + _already_compiling = True + try: - # double-check inside mutex - if self.compiled and not _new_mappers: - return self + # double-check inside mutex + if self.compiled and not _new_mappers: + return self - # initialize properties on all mappers - for mapper in list(_mapper_registry): - if not mapper.compiled: - mapper.__initialize_properties() + # initialize properties on all mappers + for mapper in list(_mapper_registry): + if not mapper.compiled: + mapper.__initialize_properties() - _new_mappers = False - return self + _new_mappers = False + return self + finally: + _already_compiling = False finally: - _already_compiling = False _COMPILE_MUTEX.release() - + def __initialize_properties(self): """Call the ``init()`` method on all ``MapperProperties`` attached to this mapper.