The fix is really simple. The patch is attached below, but previously volatile-fix of ITS is required. Also, the simple testcase (make test), with an extra yields and the couple of paranoid asserts, is: diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 3286ffb..2558d6f 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -2018,6 +2018,8 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp) if (oldest <= last) { if (!found_old) { oldest = mdb_find_oldest(txn); + /* LY: catch heisenbug. */ + mdb_tassert(txn, oldest >= env->me_pgoldest); env->me_pgoldest = oldest; found_old = 1; } @@ -2034,6 +2036,8 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp) if (oldest <= last) { if (!found_old) { oldest = mdb_find_oldest(txn); + /* LY: catch heisenbug. */ + mdb_tassert(txn, oldest >= env->me_pgoldest); env->me_pgoldest = oldest; found_old = 1; } @@ -2522,7 +2526,16 @@ mdb_txn_renew0(MDB_txn *txn) return rc; } } - txn->mt_txnid = r->mr_txnid = ti->mti_txnid; + do { + r->mr_txnid = ti->mti_txnid; + sched_yield(); + sched_yield(); + sched_yield(); + } while(r->mr_txnid != ti->mti_txnid); + sched_yield(); + sched_yield(); + sched_yield(); + txn->mt_txnid = r->mr_txnid; txn->mt_u.reader = r; meta = env->me_metas[txn->mt_txnid & 1]; }
---
The attached files is derived from OpenLDAP Software. All of the modifications to OpenLDAP Software represented in the following patch(es) were developed by Peter-Service LLC, Moscow, Russia. Peter-Service LLC has not assigned rights and/or interest in this work to any party. I, Leonid Yuriev am authorized by Peter-Service LLC, my employer, to release this work under the following terms.
Peter-Service LLC hereby places the following modifications to OpenLDAP Software (and only these modifications) into the public domain. Hence, these modifications may be freely used and/or redistributed for any purpose with or without attribution and/or other notice.
commit 6028662665c09f4d34b751bfd9b09223f6cb2433 Author: Leo Yuriev leo@yuriev.ru Date: 2014-10-17 23:29:56 +0400
ITS#7970 for LMDB: the Heisenbug.
diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 3286ffb..83a15c1 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -2522,7 +2522,12 @@ mdb_txn_renew0(MDB_txn *txn) return rc; } } - txn->mt_txnid = r->mr_txnid = ti->mti_txnid; + + do /* LY: Retry on a race, ITS#7970. */ + r->mr_txnid = ti->mti_txnid; + while(r->mr_txnid != ti->mti_txnid); + + txn->mt_txnid = r->mr_txnid; txn->mt_u.reader = r; meta = env->me_metas[txn->mt_txnid & 1]; }