[Zope-Checkins] CVS: ZODB3/BTrees - MergeTemplate.c:1.15.12.1

Tim Peters tim.one@comcast.net
Fri, 17 Jan 2003 12:29:54 -0500


Update of /cvs-repository/ZODB3/BTrees
In directory cvs.zope.org:/tmp/cvs-serv23721/BTrees

Modified Files:
      Tag: ZODB3-3_1-branch
	MergeTemplate.c 
Log Message:
Fixing a rare BTree conflict resolution error.

+ Transaction T1 deletes some of the keys in bucket B,
  but not all of the keys.

+ Transaction T2 deletes (exactly) the keys in B that
  aren't deleted by T1.

The version of B each transaction sees is then non-empty,
but conflict resolution creates an empty bucket.  However,
conflict resolution doesn't have enough info to unlink an
empty bucket from its containing BTree correctly.

The result is that an empty bucket is left in the BTree,
which violates a BTree invariant.  The most probable
symptom is a segfault, when later & unrelated code tries
to access this bucket:  an empty bucket has NULL
pointers where the vectors of keys and values should be,
and accessing code tries to dereference the NULL pointers.

I don't know that this error has been seen in real life.
It was provoked by a randomized multithreaded simulation
program that was trying to provoke errors.  This error was
provoked frequently by that program; no other kinds of
errors have come out of it.


=== ZODB3/BTrees/MergeTemplate.c 1.15 => 1.15.12.1 ===
--- ZODB3/BTrees/MergeTemplate.c:1.15	Tue Jun 25 18:02:27 2002
+++ ZODB3/BTrees/MergeTemplate.c	Fri Jan 17 12:29:21 2003
@@ -253,6 +253,15 @@
       if (i3.next(&i3) < 0) goto err;
     }
 
+  /* If the output bucket is empty, conflict resolution doesn't have
+   * enough info to unlink it from its containing BTree correctly.
+   */
+  if (r->len == 0)
+    {
+      merge_error(-1, -1, -1, 10);
+      goto err;
+    }
+
   finiSetIteration(&i1);
   finiSetIteration(&i2);
   finiSetIteration(&i3);