]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- fixed RLock-related bug in mapper which could deadlock
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 25 Sep 2008 15:59:37 +0000 (15:59 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 25 Sep 2008 15:59:37 +0000 (15:59 +0000)
upon reentrant mapper compile() calls, something that
occurs when using declarative constructs inside of
ForeignKey objects.

CHANGES
lib/sqlalchemy/orm/mapper.py

diff --git a/CHANGES b/CHANGES
index 35b8a8d28e0cf3e3413fb788751b0863898dae64..5fb8861cb042c8204492ff7866a076cc71756225 100644 (file)
--- 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
index 9c8fcf97ebe811de331c06a4832e29a8cf9ebdac..886fcec91e85efc2e064d24c737a923661fc44b4 100644 (file)
@@ -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.