[ZODB-Dev] BTree data loss bug under Python 3.x

Tres Seaver tseaver at palladion.com
Sat May 25 17:36:50 UTC 2013


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 05/25/2013 11:49 AM, Tres Seaver wrote:
> On 05/25/2013 02:50 AM, Marius Gedminas wrote:
>> On Fri, May 24, 2013 at 09:31:55PM -0400, Tres Seaver wrote:
>>> On 05/24/2013 01:28 PM, Marius Gedminas wrote:
>>>> I was trying to debug a failing ZEO test case 
>>>> (testConcurrentUpdates), and found out it had nothing to do with
>>>>  ZEO.  There's a bug either in BTrees or in ZODB itself that 
>>>> causes data corruption under Python 3.x.
>>>> 
>>>> Here's a test case: 
>>>> https://gist.github.com/mgedmin/5644876#file-zodbfail_simple-py
>>> 
>>> Thanks for the detective work!  I can confirm the bug, and that
>>> it is in the BTrees C extensions (the tests pass after 'rm 
>>> .tox/py32/lib/python3.2/site-packages/BTrees/*.so').
> 
>> It's the COMPARE macro in _compat.h.  This patch fixes the data 
>> corruption:
> 
>> diff --git a/BTrees/_compat.h b/BTrees/_compat.h index 
>> e004d54..4765df1 100644 --- a/BTrees/_compat.h +++
>> b/BTrees/_compat.h @@ -28,8 +28,8 @@ #define TEXT_FORMAT
>> PyUnicode_Format
> 
>> #define COMPARE(lhs, rhs) \ -    PyObject_RichCompareBool((lhs), 
>> (rhs), Py_LT) > 0 ? -1 : \ -    (PyObject_RichCompareBool((lhs), 
>> (rhs), Py_EQ) > 0 ? 0 : 1) +    (PyObject_RichCompareBool((lhs), 
>> (rhs), Py_LT) > 0 ? -1 : \ +     (PyObject_RichCompareBool((lhs), 
>> (rhs), Py_EQ) > 0 ? 0 : 1))
> 
> 
>> #else
> 
> 
>> I'm now trying to write a failing unit test.  It's a bit difficult
>> to get access to C macros from Python tests ;-)
> 
>> COMPARE is used in two places:
> 
>> BTrees/objectkeymacros.h-#define TEST_KEY_SET_OR(V, KEY, TARGET) \ 
>> BTrees/objectkeymacros.h:if ( ( (V) = COMPARE((KEY),(TARGET)) ), 
>> PyErr_Occurred() )
> 
>> and
> 
>> BTrees/objectvaluemacros.h:#define TEST_VALUE(VALUE, TARGET) 
>> COMPARE((VALUE),(TARGET))
> 
>> We can ignore TEST_KEY_SET_OR, as it works fine there.
> 
>> TEST_VALUE is used to implement BTree.byValue and bucket merging. 
>> The bug I was chasing down was caused by bucket mismerges, I think.
> 
>> It should be easier to write a test for byValue.  In fact there is 
>> one, in test__base.py, but it's not run against real C-implemented 
>> BTrees.  I copied it over into test_OOBTree.py and discovered that
>> it fails unexpectedly:

After adding your new test, and wrapping the 'COMPARE()' macro inside
extra parens within 'TEST_VALUE' (in 'objectvaluemacros.h'), the new
'byValue' test passes on Py3k.  I am trying to reproduce the ZEO test
failure now, and then against the BTrees trunk, before making a BTrees
release.


Tres.
- -- 
===================================================================
Tres Seaver          +1 540-429-0999          tseaver at palladion.com
Palladion Software   "Excellence by Design"    http://palladion.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with undefined - http://www.enigmail.net/

iEYEARECAAYFAlGg9rIACgkQ+gerLs4ltQ6M5ACeIyIgCC9/jWwew1qSFyJNg+eb
EDIAnRORMJ2XN7xm8kjd+lZciEaJKkA0
=iXx3
-----END PGP SIGNATURE-----



More information about the ZODB-Dev mailing list