mirror of
https://github.com/isar/libmdbx.git
synced 2025-03-04 05:08:14 +08:00
mdbx: use mdbx_jitter4testing() for race detection.
This commit is contained in:
parent
7204c46421
commit
4b2cb66453
@ -815,8 +815,11 @@ int mdbx_reader_check0(MDB_env *env, int rlocked, int *dead);
|
||||
(&((MDB_metabuf *)((env)->me_map + env->me_psize))->mb_metabuf.mm_meta)
|
||||
|
||||
static __inline MDB_meta *mdbx_meta_head(MDB_env *env) {
|
||||
mdbx_jitter4testing(true);
|
||||
MDB_meta *a = METAPAGE_1(env);
|
||||
mdbx_jitter4testing(true);
|
||||
MDB_meta *b = METAPAGE_2(env);
|
||||
mdbx_jitter4testing(true);
|
||||
|
||||
return (a->mm_txnid > b->mm_txnid) ? a : b;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ static int internal_seize_lck(HANDLE lfd) {
|
||||
assert(lfd != INVALID_HANDLE_VALUE);
|
||||
|
||||
/* 1) now on ?-? (free), get ?-E (middle) */
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (!flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER)) {
|
||||
rc = GetLastError() /* 2) something went wrong, give up */;
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
@ -202,13 +202,13 @@ static int internal_seize_lck(HANDLE lfd) {
|
||||
}
|
||||
|
||||
/* 3) now on ?-E (middle), try E-E (exclusive) */
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER))
|
||||
return MDBX_RESULT_TRUE; /* 4) got E-E (exclusive), done */
|
||||
|
||||
/* 5) still on ?-E (middle) */
|
||||
rc = GetLastError();
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) {
|
||||
/* 6) something went wrong, give up */
|
||||
if (!funlock(lfd, LCK_UPPER)) {
|
||||
@ -220,11 +220,11 @@ static int internal_seize_lck(HANDLE lfd) {
|
||||
}
|
||||
|
||||
/* 7) still on ?-E (middle), try S-E (locked) */
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER) ? MDBX_RESULT_FALSE
|
||||
: GetLastError();
|
||||
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (rc != MDBX_RESULT_FALSE)
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"?-E(middle) >> S-E(locked)", rc);
|
||||
@ -247,7 +247,7 @@ int mdbx_lck_seize(MDB_env *env) {
|
||||
assert(env->me_fd != INVALID_HANDLE_VALUE);
|
||||
if (env->me_lfd == INVALID_HANDLE_VALUE) {
|
||||
/* LY: without-lck mode (e.g. on read-only filesystem) */
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (!flock(env->me_fd, LCK_SHARED | LCK_DONTWAIT, LCK_WHOLE)) {
|
||||
rc = GetLastError();
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_, "without-lck", rc);
|
||||
@ -257,7 +257,7 @@ int mdbx_lck_seize(MDB_env *env) {
|
||||
}
|
||||
|
||||
rc = internal_seize_lck(env->me_lfd);
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (rc == MDBX_RESULT_TRUE && (env->me_flags & MDB_RDONLY) == 0) {
|
||||
/* Check that another process don't operates in without-lck mode.
|
||||
* Doing such check by exclusive locking the body-part of db. Should be
|
||||
@ -269,10 +269,10 @@ int mdbx_lck_seize(MDB_env *env) {
|
||||
rc = GetLastError();
|
||||
mdbx_error("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
"lock-against-without-lck", rc);
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
mdbx_lck_destroy(env);
|
||||
} else {
|
||||
jitter4testing();
|
||||
mdbx_jitter4testing(false);
|
||||
if (!funlock(env->me_fd, LCK_BODY)) {
|
||||
rc = GetLastError();
|
||||
mdbx_panic("%s(%s) failed: errcode %u", mdbx_func_,
|
||||
|
30
src/mdbx.c
30
src/mdbx.c
@ -1412,6 +1412,7 @@ static txnid_t mdbx_find_oldest(MDB_env *env, int *laggard) {
|
||||
const MDB_reader *const r = env->me_lck->mti_readers;
|
||||
for (reader = -1, i = env->me_lck->mti_numreaders; --i >= 0;) {
|
||||
if (r[i].mr_pid) {
|
||||
mdbx_jitter4testing(true);
|
||||
txnid_t snap = r[i].mr_txnid;
|
||||
if (oldest > snap) {
|
||||
oldest = snap;
|
||||
@ -2187,9 +2188,13 @@ static int mdbx_txn_renew0(MDB_txn *txn, unsigned flags) {
|
||||
|
||||
while (1) {
|
||||
MDB_meta *const meta = mdbx_meta_head(txn->mt_env);
|
||||
mdbx_jitter4testing(false);
|
||||
const txnid_t snap = meta->mm_txnid;
|
||||
mdbx_jitter4testing(false);
|
||||
r->mr_txnid = snap;
|
||||
mdbx_jitter4testing(false);
|
||||
mdbx_coherent_barrier();
|
||||
mdbx_jitter4testing(true);
|
||||
|
||||
/* Snap the state from current meta-head */
|
||||
txn->mt_txnid = snap;
|
||||
@ -2206,21 +2211,16 @@ static int mdbx_txn_renew0(MDB_txn *txn, unsigned flags) {
|
||||
txn->mt_dbxs = env->me_dbxs; /* mostly static anyway */
|
||||
} else {
|
||||
/* Not yet touching txn == env->me_txn0, it may be active */
|
||||
mdbx_jitter4testing(false);
|
||||
rc = mdbx_txn_lock(env);
|
||||
if (unlikely(rc))
|
||||
return rc;
|
||||
|
||||
mdbx_jitter4testing(false);
|
||||
MDB_meta *meta = mdbx_meta_head(env);
|
||||
mdbx_jitter4testing(false);
|
||||
txn->mt_canary = meta->mm_canary;
|
||||
txn->mt_txnid = meta->mm_txnid + 1;
|
||||
if (unlikely(txn->mt_txnid < meta->mm_txnid)) {
|
||||
mdbx_debug("txnid overflow!");
|
||||
rc = MDB_TXN_FULL;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
txn->mt_flags = flags;
|
||||
|
||||
#if MDB_DEBUG
|
||||
if (unlikely(txn->mt_txnid == mdbx_debug_edge)) {
|
||||
if (!mdbx_debug_logger)
|
||||
@ -2230,6 +2230,13 @@ static int mdbx_txn_renew0(MDB_txn *txn, unsigned flags) {
|
||||
"on/off edge (txn %zu)", txn->mt_txnid);
|
||||
}
|
||||
#endif
|
||||
if (unlikely(txn->mt_txnid < meta->mm_txnid)) {
|
||||
mdbx_debug("txnid overflow!");
|
||||
rc = MDB_TXN_FULL;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
txn->mt_flags = flags;
|
||||
txn->mt_child = NULL;
|
||||
txn->mt_loose_pgs = NULL;
|
||||
txn->mt_loose_count = 0;
|
||||
@ -3834,6 +3841,13 @@ static int __cold mdbx_setup_lck(MDB_env *env, char *lck_pathname, int mode) {
|
||||
off_t wanna = roundup2((env->me_maxreaders - 1) * sizeof(MDB_reader) +
|
||||
sizeof(MDBX_lockinfo),
|
||||
env->me_os_psize);
|
||||
#ifndef NDEBUG
|
||||
err = mdbx_ftruncate(env->me_lfd, size = 0);
|
||||
if (unlikely(err != MDB_SUCCESS))
|
||||
return err;
|
||||
#endif
|
||||
mdbx_jitter4testing(false);
|
||||
|
||||
if (size != wanna) {
|
||||
err = mdbx_ftruncate(env->me_lfd, wanna);
|
||||
if (unlikely(err != MDB_SUCCESS))
|
||||
|
Loading…
x
Reference in New Issue
Block a user