mdbx: устранение регресса не-отпускания мьютекса при попытки повторного закрытия dbi-хендла.

Ошибка была внесена 2024-10-23 коммитом v0.13.1-35-g3049bb87b5b14d83b16d121c186ce8fb3f21383e.
This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2024-12-22 09:25:28 +03:00
parent a76e06a48e
commit bfc6795762
1 changed files with 50 additions and 45 deletions

View File

@ -146,13 +146,18 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
if (unlikely(dbi >= env->max_dbi)) if (unlikely(dbi >= env->max_dbi))
return LOG_IFERR(MDBX_BAD_DBI); return LOG_IFERR(MDBX_BAD_DBI);
if (unlikely(dbi < CORE_DBS || dbi >= env->max_dbi))
return LOG_IFERR(MDBX_BAD_DBI);
rc = osal_fastmutex_acquire(&env->dbi_lock); rc = osal_fastmutex_acquire(&env->dbi_lock);
if (likely(rc == MDBX_SUCCESS && dbi < env->n_dbi)) { if (unlikely(rc != MDBX_SUCCESS))
retry: return LOG_IFERR(rc);
if (env->basal_txn && (env->dbs_flags[dbi] & DB_VALID) && (env->basal_txn->flags & MDBX_TXN_FINISHED) == 0) {
if (unlikely(dbi >= env->n_dbi)) {
rc = MDBX_BAD_DBI;
bailout:
osal_fastmutex_release(&env->dbi_lock);
return LOG_IFERR(rc);
}
while (env->basal_txn && (env->dbs_flags[dbi] & DB_VALID) && (env->basal_txn->flags & MDBX_TXN_FINISHED) == 0) {
/* LY: Опасный код, так как env->txn может быть изменено в другом потоке. /* LY: Опасный код, так как env->txn может быть изменено в другом потоке.
* К сожалению тут нет надежного решения и может быть падение при неверном * К сожалению тут нет надежного решения и может быть падение при неверном
* использовании API (вызове mdbx_dbi_close конкурентно с завершением * использовании API (вызове mdbx_dbi_close конкурентно с завершением
@ -176,23 +181,23 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
const MDBX_txn *const hazard = env->txn; const MDBX_txn *const hazard = env->txn;
osal_compiler_barrier(); osal_compiler_barrier();
if ((dbi_state(env->basal_txn, dbi) & (DBI_LINDO | DBI_DIRTY | DBI_CREAT)) > DBI_LINDO) { if ((dbi_state(env->basal_txn, dbi) & (DBI_LINDO | DBI_DIRTY | DBI_CREAT)) > DBI_LINDO) {
bailout_dirty_dbi: rc = MDBX_DANGLING_DBI;
osal_fastmutex_release(&env->dbi_lock); goto bailout;
return LOG_IFERR(MDBX_DANGLING_DBI);
} }
osal_memory_barrier(); osal_memory_barrier();
if (unlikely(hazard != env->txn)) if (unlikely(hazard != env->txn))
goto retry; continue;
if (hazard != env->basal_txn && hazard && (hazard->flags & MDBX_TXN_FINISHED) == 0 && if (hazard != env->basal_txn && hazard && (hazard->flags & MDBX_TXN_FINISHED) == 0 &&
hazard->signature == txn_signature && hazard->signature == txn_signature &&
(dbi_state(hazard, dbi) & (DBI_LINDO | DBI_DIRTY | DBI_CREAT)) > DBI_LINDO) (dbi_state(hazard, dbi) & (DBI_LINDO | DBI_DIRTY | DBI_CREAT)) > DBI_LINDO) {
goto bailout_dirty_dbi; rc = MDBX_DANGLING_DBI;
goto bailout;
}
osal_compiler_barrier(); osal_compiler_barrier();
if (unlikely(hazard != env->txn)) if (likely(hazard == env->txn))
goto retry; break;
} }
rc = dbi_close_release(env, dbi); rc = dbi_close_release(env, dbi);
}
return LOG_IFERR(rc); return LOG_IFERR(rc);
} }