mdbx-test: add workaround for CLANG/LLVM STL stupidity of std::set<>.

This commit is contained in:
Leonid Yuriev 2021-07-03 13:01:41 +00:00
parent cf5f31c577
commit c4a696be1d
2 changed files with 27 additions and 7 deletions

View File

@ -110,16 +110,24 @@ bool testcase_nested::teardown() {
}
void testcase_nested::push_txn() {
MDBX_txn *txn;
MDBX_txn *nested_txn;
MDBX_txn_flags_t flags = MDBX_txn_flags_t(
prng32() & uint32_t(MDBX_TXN_NOSYNC | MDBX_TXN_NOMETASYNC));
int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &txn);
int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &nested_txn);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_txn_begin(nested)", err);
stack.emplace(scoped_txn_guard(txn), serial, fifo, speculum);
std::swap(txn_guard, std::get<0>(stack.top()));
/* CLANG/LLVM C++ library could stupidly copy std::set<> item-by-item,
* i.e. with insertion(s) & comparison(s), which will cause null dereference
* during call mdbx_cmp() with zero txn. So it is the workaround for this:
* - explicitly set txn_guard with the new nested txn;
* - explicitly copy the `speculum` (an instance of std::set<>). */
scoped_txn_guard nested_txn_guard(nested_txn);
txn_guard.swap(nested_txn_guard);
SET speculum_snapshot(speculum);
stack.emplace(std::move(nested_txn_guard), serial, fifo,
std::move(speculum_snapshot));
log_verbose("begin level#%zu txn #%" PRIu64 ", flags 0x%x, serial %" PRIu64,
stack.size(), mdbx_txn_id(txn), flags, serial);
stack.size(), mdbx_txn_id(nested_txn), flags, serial);
}
bool testcase_nested::pop_txn(bool abort) {

View File

@ -197,6 +197,18 @@ int testcase::breakable_commit() {
log_trace(">> txn_commit");
assert(txn_guard);
/* CLANG/LLVM C++ library could stupidly copy std::set<> item-by-item,
* i.e. with insertion(s) & comparison(s), which will cause null dereference
* during call mdbx_cmp() with zero txn. So it is the workaround for this:
* - explicitly make copies of the `speculums`;
* - explicitly move relevant copy after transaction commit. */
SET speculum_committed_copy(ItemCompare(this)),
speculum_copy(ItemCompare(this));
if (need_speculum_assign) {
speculum_committed_copy = speculum_committed;
speculum_copy = speculum;
}
MDBX_txn *txn = txn_guard.release();
txn_inject_writefault(txn);
int rc = mdbx_txn_commit(txn);
@ -207,9 +219,9 @@ int testcase::breakable_commit() {
if (need_speculum_assign) {
need_speculum_assign = false;
if (unlikely(rc != MDBX_SUCCESS))
speculum = speculum_committed;
speculum = std::move(speculum_committed_copy);
else
speculum_committed = speculum;
speculum_committed = std::move(speculum_copy);
}
log_trace("<< txn_commit: %s", rc ? "failed" : "Ok");