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(a)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];
}