[Zodb-checkins] SVN: ZODB/branches/3.9/src/ Bug Fixed:

Jim Fulton jim at zope.com
Mon Dec 14 14:27:08 EST 2009


Log message for revision 106502:
  Bug Fixed:
  
  A ZEO threading bug could cause transactions to read inconsistent
    data.  (This sometimes caused an AssertionError in
    Connection._setstate_noncurrent.)
  

Changed:
  U   ZODB/branches/3.9/src/CHANGES.txt
  U   ZODB/branches/3.9/src/ZEO/ClientStorage.py
  U   ZODB/branches/3.9/src/ZODB/Connection.py

-=-
Modified: ZODB/branches/3.9/src/CHANGES.txt
===================================================================
--- ZODB/branches/3.9/src/CHANGES.txt	2009-12-14 18:46:46 UTC (rev 106501)
+++ ZODB/branches/3.9/src/CHANGES.txt	2009-12-14 19:27:08 UTC (rev 106502)
@@ -8,6 +8,10 @@
 Bugs Fixed
 ----------
 
+- A ZEO threading bug could cause transactions to read inconsistent
+  data.  (This sometimes caused an AssertionError in
+  Connection._setstate_noncurrent.)
+
 - DemoStorage.loadBefore sometimes returned invalid data which
   would trigger AssertionErrors in ZODB.Connection.
 

Modified: ZODB/branches/3.9/src/ZEO/ClientStorage.py
===================================================================
--- ZODB/branches/3.9/src/ZEO/ClientStorage.py	2009-12-14 18:46:46 UTC (rev 106501)
+++ ZODB/branches/3.9/src/ZEO/ClientStorage.py	2009-12-14 19:27:08 UTC (rev 106502)
@@ -1143,15 +1143,12 @@
                 raise ClientDisconnected(
                        'Calling tpc_finish() on a disconnected transaction')
 
-            # The calls to tpc_finish() and _update_cache() should
-            # never run currently with another thread, because the
-            # tpc_cond condition variable prevents more than one
-            # thread from calling tpc_finish() at a time.
-            tid = self._server.tpc_finish(id(txn))
-
+            finished = 0
             try:
                 self._lock.acquire()  # for atomic processing of invalidations
                 try:
+                    tid = self._server.tpc_finish(id(txn))
+                    finished = 1
                     self._update_cache(tid)
                     if f is not None:
                         f(tid)
@@ -1161,9 +1158,10 @@
                 r = self._check_serials()
                 assert r is None or len(r) == 0, "unhandled serialnos: %s" % r
             except:
-                # The server successfully committed.  If we get a failure
-                # here, our own state will be in question, so reconnect.
-                self._connection.close()
+                if finished:
+                    # The server successfully committed.  If we get a failure
+                    # here, our own state will be in question, so reconnect.
+                    self._connection.close()
                 raise
 
             self.end_transaction()

Modified: ZODB/branches/3.9/src/ZODB/Connection.py
===================================================================
--- ZODB/branches/3.9/src/ZODB/Connection.py	2009-12-14 18:46:46 UTC (rev 106501)
+++ ZODB/branches/3.9/src/ZODB/Connection.py	2009-12-14 19:27:08 UTC (rev 106502)
@@ -341,6 +341,10 @@
         try:
             if self._txn_time is None:
                 self._txn_time = tid
+            elif tid < self._txn_time:
+                raise AssertionError("invalidations out of order, %r < %r"
+                                     % (tid, self._txn_time))
+
             self._invalidated.update(oids)
         finally:
             self._inv_lock.release()



More information about the Zodb-checkins mailing list