web/views/authentication.py
changeset 5251 b675edd05c19
parent 5223 6abd6e3599f4
child 5423 e15abfdcce38
--- a/web/views/authentication.py	Wed Apr 14 17:31:41 2010 +0200
+++ b/web/views/authentication.py	Wed Apr 14 17:38:24 2010 +0200
@@ -5,8 +5,12 @@
 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
 """
+from __future__ import with_statement
+
 __docformat__ = "restructuredtext en"
 
+from threading import Lock
+
 from logilab.common.decorators import clear_cache
 
 from cubicweb import AuthenticationError, BadConnectionId
@@ -76,25 +80,32 @@
         """
         # with this authentication manager, session is actually a dbapi
         # connection
-        cnx = session.cnx
         login = req.get_authorization()[0]
-        # check cnx.login and not user.login, since in case of login by
+        # check session.login and not user.login, since in case of login by
         # email, login and cnx.login are the email while user.login is the
         # actual user login
         if login and session.login != login:
             raise InvalidSession('login mismatch')
         try:
-            # calling cnx.user() check connection validity, raise
-            # BadConnectionId on failure
-            user = cnx.user(req)
-        except BadConnectionId:
-            # check if a connection should be automatically restablished
-            if (login is None or login == session.login):
-                cnx = self._authenticate(session.login, session.authinfo)
+            lock = session.reconnection_lock
+        except AttributeError:
+            lock = session.reconnection_lock = Lock()
+        # need to be locked two avoid duplicated reconnections on concurrent
+        # requests
+        with lock:
+            cnx = session.cnx
+            try:
+                # calling cnx.user() check connection validity, raise
+                # BadConnectionId on failure
                 user = cnx.user(req)
-                session.cnx = cnx
-            else:
-                raise InvalidSession('bad connection id')
+            except BadConnectionId:
+                # check if a connection should be automatically restablished
+                if (login is None or login == session.login):
+                    cnx = self._authenticate(session.login, session.authinfo)
+                    user = cnx.user(req)
+                    session.cnx = cnx
+                else:
+                    raise InvalidSession('bad connection id')
         return user
 
     def authenticate(self, req):