[session] lock self._closed and session.close to avoid race conditions stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 09 May 2011 14:35:10 +0200
branchstable
changeset 7340 9303fd71c2ee
parent 7339 dd5e49a5dcab
child 7341 c419c2d0d13e
[session] lock self._closed and session.close to avoid race conditions
server/session.py
--- a/server/session.py	Mon May 09 14:34:23 2011 +0200
+++ b/server/session.py	Mon May 09 14:35:10 2011 +0200
@@ -182,6 +182,7 @@
         self.__threaddata = threading.local()
         self._threads_in_transaction = set()
         self._closed = False
+        self._closed_lock = threading.Lock()
 
     def __unicode__(self):
         return '<%ssession %s (%s 0x%x)>' % (
@@ -618,21 +619,22 @@
 
     def set_pool(self):
         """the session need a pool to execute some queries"""
-        if self._closed:
-            self.reset_pool(True)
-            raise Exception('try to set pool on a closed session')
-        if self.pool is None:
-            # get pool first to avoid race-condition
-            self._threaddata.pool = pool = self.repo._get_pool()
-            try:
-                pool.pool_set()
-            except:
-                self._threaddata.pool = None
-                self.repo._free_pool(pool)
-                raise
-            self._threads_in_transaction.add(
-                (threading.currentThread(), pool) )
-        return self._threaddata.pool
+        with self._closed_lock:
+            if self._closed:
+                self.reset_pool(True)
+                raise Exception('try to set pool on a closed session')
+            if self.pool is None:
+                # get pool first to avoid race-condition
+                self._threaddata.pool = pool = self.repo._get_pool()
+                try:
+                    pool.pool_set()
+                except:
+                    self._threaddata.pool = None
+                    self.repo._free_pool(pool)
+                    raise
+                self._threads_in_transaction.add(
+                    (threading.currentThread(), pool) )
+            return self._threaddata.pool
 
     def _free_thread_pool(self, thread, pool, force_close=False):
         try:
@@ -870,7 +872,8 @@
 
     def close(self):
         """do not close pool on session close, since they are shared now"""
-        self._closed = True
+        with self._closed_lock:
+            self._closed = True
         # copy since _threads_in_transaction maybe modified while waiting
         for thread, pool in self._threads_in_transaction.copy():
             if thread is threading.currentThread():