Commit f8cf23ec authored by Jason Madden's avatar Jason Madden

Don't manipulate Connection state after it has been returned to the pool.

Doing so leads to race conditions.

In particular, there can be an AttributeError.

See https://github.com/zodb/zodbshootout/issues/26 for details.
parent f3b2350a
...@@ -10,6 +10,11 @@ ...@@ -10,6 +10,11 @@
See `issue 139 <https://github.com/zopefoundation/ZODB/issues/139`_. See `issue 139 <https://github.com/zopefoundation/ZODB/issues/139`_.
- ``persistent`` is no longer required at setup time. - ``persistent`` is no longer required at setup time.
See `issue 119 <https://github.com/zopefoundation/ZODB/issues/119>`_. See `issue 119 <https://github.com/zopefoundation/ZODB/issues/119>`_.
- ``Connection.close`` and ``Connection.open`` no longer race on
``self.transaction_manager``, which could lead to
``AttributeError``. This was a bug introduced in 5.0.1. See `issue
142 <https://github.com/zopefoundation/ZODB/pull/143>`_.
5.1.1 (2016-11-18) 5.1.1 (2016-11-18)
================== ==================
......
...@@ -304,6 +304,14 @@ class Connection(ExportImport, object): ...@@ -304,6 +304,14 @@ class Connection(ExportImport, object):
# closed the DB already, .e.g, ZODB.connection() does this. # closed the DB already, .e.g, ZODB.connection() does this.
self.transaction_manager.unregisterSynch(self) self.transaction_manager.unregisterSynch(self)
am = self._db._activity_monitor
if am is not None:
am.closedConnection(self)
# Drop transaction manager to release resources and help prevent errors
self.transaction_manager = None
if primary: if primary:
for connection in self.connections.values(): for connection in self.connections.values():
if connection is not self: if connection is not self:
...@@ -320,12 +328,9 @@ class Connection(ExportImport, object): ...@@ -320,12 +328,9 @@ class Connection(ExportImport, object):
else: else:
self.opened = None self.opened = None
am = self._db._activity_monitor # We may have been reused by another thread at this point so
if am is not None: # we can't manipulate or check the state of `self` any more.
am.closedConnection(self)
# Drop transaction manager to release resources and help prevent errors
self.transaction_manager = None
def db(self): def db(self):
"""Returns a handle to the database this connection belongs to.""" """Returns a handle to the database this connection belongs to."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment