From 945899e4fdc5f0a1a471a90c1d72b1c1fa014603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Sat, 26 Oct 2024 01:16:20 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20`mdbx=5Fclose=5Fdbi()`=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BF=D1=8B=D1=82=D0=BA=D0=B5=20=D0=B7=D0=B0=D0=BA?= =?UTF-8?q?=D1=80=D1=8B=D1=82=D1=8C=20dbi-=D1=85=D0=B5=D0=BD=D0=B4=D0=BB?= =?UTF-8?q?=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9?= =?UTF-8?q?=20=D0=B2=20=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B0=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=8B=20(ba?= =?UTF-8?q?ckport).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog.md | 10 ++++++++++ src/core.c | 26 +++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 157e2235..08c2aaf9 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,16 @@ and [by Yandex](https://translated.turbopages.org/proxy_u/ru-en.en/https/gitflic изменения геометрии другим процессом с увеличением верхнего размера БД и увеличением БД больше предыдущего лимита. + - Доработка `mdbx_close_dbi()` для возврата ошибки при попытке закрыть + dbi-дескриптор таблицы, созданной и/или измененной в ещё выполняющейся + транзакции. Такое преждевременное закрытие дескриптора является неверным + использованием API и нарушением контракта/предусловий сформулированных + в описании `mdbx_close_dbi()`. Однако, вместо возврата ошибки + выполнялось некорректное закрытие дескриптора, что могло приводить к + созданию таблицы с пустым именем, утечки страниц БД и/или нарушению + структуры b-tree (неверной ссылкой на корень таблицы). + + -------------------------------------------------------------------------------- diff --git a/src/core.c b/src/core.c index 2b6bf969..b0e9de7b 100644 --- a/src/core.c +++ b/src/core.c @@ -23134,9 +23134,29 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) { rc = osal_fastmutex_acquire(&env->me_dbi_lock); if (likely(rc == MDBX_SUCCESS)) { - rc = (dbi < env->me_maxdbs && (env->me_dbflags[dbi] & DB_VALID)) - ? dbi_close_locked(env, dbi) - : MDBX_BAD_DBI; + retry: + rc = MDBX_BAD_DBI; + if (dbi < env->me_maxdbs && (env->me_dbflags[dbi] & DB_VALID)) { + const MDBX_txn *const hazard = env->me_txn; + osal_compiler_barrier(); + if (env->me_txn0 && (env->me_txn0->mt_flags & MDBX_TXN_FINISHED) == 0) { + if (env->me_txn0->mt_dbistate[dbi] & (DBI_DIRTY | DBI_CREAT)) + goto bailout_dirty_dbi; + osal_memory_barrier(); + if (unlikely(hazard != env->me_txn)) + goto retry; + if (hazard != env->me_txn0 && hazard && + (hazard->mt_flags & MDBX_TXN_FINISHED) == 0 && + hazard->mt_signature == MDBX_MT_SIGNATURE && + (hazard->mt_dbistate[dbi] & (DBI_DIRTY | DBI_CREAT))) + goto bailout_dirty_dbi; + osal_compiler_barrier(); + if (unlikely(hazard != env->me_txn)) + goto retry; + } + rc = dbi_close_locked(env, dbi); + } + bailout_dirty_dbi: ENSURE(env, osal_fastmutex_release(&env->me_dbi_lock) == MDBX_SUCCESS); } return rc;