# HG changeset patch
# Parent 2fd35685f8d81b1cf7bfa69f44f10e212c88562e
web: avoid using a cursor after the connection from which it depends has been rollbacked (as this doesn't work with PySqlite due to some explicit close on rollback we do).
We simply bail out after the rollback, as if we get there it's because there was a concurrent request which already save the session attributes for the same sesion, and performed the same expiration checks.
Closes #9104.
diff --git a/trac/web/session.py b/trac/web/session.py
|
a
|
b
|
class DetachedSession(dict): |
| 94 | 94 | db.rollback() |
| 95 | 95 | self.env.log.warning('Session %s already exists: %s' % |
| 96 | 96 | (self.sid, e)) |
| | 97 | return |
| | 98 | |
| 97 | 99 | if self._old != self: |
| 98 | 100 | attrs = [(self.sid, authenticated, k, v) for k, v in self.items()] |
| 99 | 101 | cursor.execute("DELETE FROM session_attribute WHERE sid=%s", |
| 100 | 102 | (self.sid,)) |
| 101 | 103 | self._old = dict(self.items()) |
| 102 | 104 | if attrs: |
| 103 | | # The session variables might already have been updated by a |
| 104 | | # concurrent request. |
| 105 | | try: |
| 106 | | cursor.executemany("INSERT INTO session_attribute " |
| 107 | | "(sid,authenticated,name,value) " |
| 108 | | "VALUES(%s,%s,%s,%s)", attrs) |
| 109 | | except Exception, e: |
| 110 | | db.rollback() |
| 111 | | self.env.log.warning('Attributes for session %s already ' |
| 112 | | 'updated: %s' % (self.sid, e)) |
| | 105 | cursor.executemany("INSERT INTO session_attribute " |
| | 106 | "(sid,authenticated,name,value) " |
| | 107 | "VALUES(%s,%s,%s,%s)", attrs) |
| 113 | 108 | elif not authenticated: |
| 114 | 109 | # No need to keep around empty unauthenticated sessions |
| 115 | 110 | cursor.execute("DELETE FROM session " |