mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-30 11:29:19 +08:00
mdbx: костыль для глушения/игнорирования EDEADLK
в ряде сценариев при использовании Valgrind или ASAN.
Достаточно запутанно: - Для полноценного контроля при использовании Valgrind или ASAN требуется закрашивать/отравлять отображение файла БД выше границы распределенных страниц. - Производить такое подкрашивание/отравление необходимо в синхронизации с пишущими транзакциями и запросами на изменение геометрии, в том числе при изменении размера БД и/или геометрии другим процессом. - Для такой синхронизации логично и проще всего использовать основной мьютекс/механизм блокировки пишущих транзакций, что и происходит внутри txn_valgrind(). - Однако, в этой схеме может возникать ошибка EDEADLK, когда txn_valgrind() вызывается при завершении читающей транзакции выполняющейся с дополнительной блокировкой пишущих транзакций. - Как таковая ошибка EDEADLK при этом проблем не создаёт и поэтому просто игнорируется. Но утилита mdbx_chk при работе в кооперативном (не эксклюзивном) режиме чтения-записи использует именно такой сценарий, а возникающую при этом ошибку EDEADLK засчитывает как проблему при проверке. = В результате, при использовании Valgrind или ASAN утилита mdbx_chk запущенная с опциями `-wc` всегда завершается неудачей из-за как минимум одной проблемы в ходе проверки. Что внешне выглядит как недочет/ошибка/регресс и создает проблемы при автоматизированном тестировании. Добавленный костыль использует atomic-счетчик, который инкремируется до и декремируется после попытки захвата блокировки изнутри txn_valgrind(). В свою очередь, код обрабатывающий ошибку захвата блокировки, игнорирует EDEADLK при ненулевом значении счетчика. Активируется костыль только при сборке с поддержкой Valgrind или включенном ASAN, и не оказывает никакого влияния в остальных случаях.
This commit is contained in:
parent
45721d4064
commit
1aead6869a
10
src/core.c
10
src/core.c
@ -9131,7 +9131,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) {
|
||||
}
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
txn_valgrind(env, txn);
|
||||
#endif
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
txn->mt_owner = tid;
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
@ -9813,8 +9813,10 @@ static int txn_end(MDBX_txn *txn, const unsigned mode) {
|
||||
txn->mt_txnid == slot->mr_txnid.weak &&
|
||||
slot->mr_txnid.weak >= env->me_lck->mti_oldest_reader.weak);
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
atomic_add32(&env->me_ignore_EDEADLK, 1);
|
||||
txn_valgrind(env, nullptr);
|
||||
#endif
|
||||
atomic_sub32(&env->me_ignore_EDEADLK, 1);
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
atomic_store32(&slot->mr_snapshot_pages_used, 0, mo_Relaxed);
|
||||
safe64_reset(&slot->mr_txnid, false);
|
||||
atomic_store32(&env->me_lck->mti_readers_refresh_flag, true,
|
||||
@ -9843,7 +9845,7 @@ static int txn_end(MDBX_txn *txn, const unsigned mode) {
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
if (txn == env->me_txn0)
|
||||
txn_valgrind(env, nullptr);
|
||||
#endif
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
|
||||
txn->mt_flags = MDBX_TXN_FINISHED;
|
||||
txn->mt_owner = 0;
|
||||
@ -15292,7 +15294,7 @@ bailout:
|
||||
} else {
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
txn_valgrind(env, nullptr);
|
||||
#endif
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
}
|
||||
osal_free(env_pathname.buffer_for_free);
|
||||
return rc;
|
||||
|
@ -1482,6 +1482,7 @@ struct MDBX_env {
|
||||
int me_valgrind_handle;
|
||||
#endif
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
MDBX_atomic_uint32_t me_ignore_EDEADLK;
|
||||
pgno_t me_poison_edge;
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
|
||||
|
@ -822,6 +822,11 @@ __cold static int mdbx_ipclock_failed(MDBX_env *env, osal_ipclock_t *ipc,
|
||||
#error "FIXME"
|
||||
#endif /* MDBX_LOCKING */
|
||||
|
||||
#if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__)
|
||||
if (rc == EDEADLK && atomic_load32(&env->me_ignore_EDEADLK, mo_Relaxed) > 0)
|
||||
return rc;
|
||||
#endif /* MDBX_USE_VALGRIND || __SANITIZE_ADDRESS__ */
|
||||
|
||||
ERROR("mutex (un)lock failed, %s", mdbx_strerror(err));
|
||||
if (rc != EDEADLK)
|
||||
env->me_flags |= MDBX_FATAL_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user