From af4dfe541b83938ff67ea48012b8c78f3226691a 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, 11 Nov 2023 20:08:04 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20`mdbx=5Fenv=5Fresurrect=5Fafter=5Ffo?= =?UTF-8?q?rk()`=20=D0=B2=20API.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mdbx.h | 5 +++ src/core.c | 109 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 78 insertions(+), 36 deletions(-) diff --git a/mdbx.h b/mdbx.h index e2da78b3..ce2dad5e 100644 --- a/mdbx.h +++ b/mdbx.h @@ -2895,6 +2895,11 @@ LIBMDBX_INLINE_API(int, mdbx_env_close, (MDBX_env * env)) { return mdbx_env_close_ex(env, false); } +#if !(defined(_WIN32) || defined(_WIN64)) +/** FIXME */ +LIBMDBX_API int mdbx_env_resurrect_after_fork(MDBX_env *env); +#endif /* Windows */ + /** \brief Warming up options * \ingroup c_settings * \anchor warmup_flags diff --git a/src/core.c b/src/core.c index 8138dcaf..81d62e69 100644 --- a/src/core.c +++ b/src/core.c @@ -3317,7 +3317,7 @@ static int __must_check_result read_header(MDBX_env *env, MDBX_meta *meta, static int __must_check_result sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, meta_troika_t *const troika); -static int env_close(MDBX_env *env); +static int env_close(MDBX_env *env, bool resurrect_after_fork); struct node_result { MDBX_node *node; @@ -15668,7 +15668,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname, #endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */ } else { bailout: - if (likely(env_close(env) == MDBX_SUCCESS)) { + if (likely(env_close(env, false) == MDBX_SUCCESS)) { env->me_flags = saved_me_flags; } else { rc = MDBX_PANIC; @@ -15679,7 +15679,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname, } /* Destroy resources from mdbx_env_open(), clear our readers & DBIs */ -__cold static int env_close(MDBX_env *env) { +__cold static int env_close(MDBX_env *env, bool resurrect_after_fork) { const unsigned flags = env->me_flags; env->me_flags &= ~ENV_INTERNAL_FLAGS; if (flags & MDBX_ENV_TXKEY) { @@ -15724,6 +15724,7 @@ __cold static int env_close(MDBX_env *env) { CloseHandle(env->me_data_lock_event); env->me_data_lock_event = INVALID_HANDLE_VALUE; } + eASSERT(env, !resurrect_after_fork); if (env->me_pathname_char) { osal_free(env->me_pathname_char); env->me_pathname_char = nullptr; @@ -15745,43 +15746,79 @@ __cold static int env_close(MDBX_env *env) { env->me_lfd = INVALID_HANDLE_VALUE; } - if (env->me_dbxs) { - for (size_t i = CORE_DBS; i < env->me_numdbs; ++i) - if (env->me_dbxs[i].md_name.iov_len) - osal_free(env->me_dbxs[i].md_name.iov_base); - osal_free(env->me_dbxs); - env->me_numdbs = CORE_DBS; - env->me_dbxs = nullptr; - } - if (env->me_pbuf) { - osal_memalign_free(env->me_pbuf); - env->me_pbuf = nullptr; - } - if (env->me_dbi_seqs) { - osal_free(env->me_dbi_seqs); - env->me_dbi_seqs = nullptr; - } - if (env->me_db_flags) { - osal_free(env->me_db_flags); - env->me_db_flags = nullptr; - } - if (env->me_pathname.buffer) { - osal_free(env->me_pathname.buffer); - env->me_pathname.buffer = nullptr; - } - if (env->me_txn0) { - dpl_free(env->me_txn0); - txl_free(env->me_txn0->tw.lifo_reclaimed); - pnl_free(env->me_txn0->tw.retired_pages); - pnl_free(env->me_txn0->tw.spilled.list); - pnl_free(env->me_txn0->tw.relist); - osal_free(env->me_txn0); - env->me_txn0 = nullptr; + if (!resurrect_after_fork) { + if (env->me_dbxs) { + for (size_t i = CORE_DBS; i < env->me_numdbs; ++i) + if (env->me_dbxs[i].md_name.iov_len) + osal_free(env->me_dbxs[i].md_name.iov_base); + osal_free(env->me_dbxs); + env->me_numdbs = CORE_DBS; + env->me_dbxs = nullptr; + } + if (env->me_pbuf) { + osal_memalign_free(env->me_pbuf); + env->me_pbuf = nullptr; + } + if (env->me_dbi_seqs) { + osal_free(env->me_dbi_seqs); + env->me_dbi_seqs = nullptr; + } + if (env->me_db_flags) { + osal_free(env->me_db_flags); + env->me_db_flags = nullptr; + } + if (env->me_pathname.buffer) { + osal_free(env->me_pathname.buffer); + env->me_pathname.buffer = nullptr; + } + if (env->me_txn0) { + dpl_free(env->me_txn0); + txl_free(env->me_txn0->tw.lifo_reclaimed); + pnl_free(env->me_txn0->tw.retired_pages); + pnl_free(env->me_txn0->tw.spilled.list); + pnl_free(env->me_txn0->tw.relist); + osal_free(env->me_txn0); + env->me_txn0 = nullptr; + } } env->me_stuck_meta = -1; return rc; } +#if !(defined(_WIN32) || defined(_WIN64)) +__cold int mdbx_env_resurrect_after_fork(MDBX_env *env) { + if (unlikely(!env)) + return MDBX_EINVAL; + + if (unlikely(env->me_signature.weak != MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) + return MDBX_PANIC; + + const uint32_t new_pid = osal_getpid(); + if (unlikely(env->me_pid == new_pid)) + return MDBX_SUCCESS; + + if (!atomic_cas32(&env->me_signature, MDBX_ME_SIGNATURE, ~MDBX_ME_SIGNATURE)) + return MDBX_EBADSIGN; + + if (env->me_txn) + txn_abort(env->me_txn0); + env->me_live_reader = 0; + int rc = env_close(env, true); + env->me_signature.weak = MDBX_ME_SIGNATURE; + if (likely(rc == MDBX_SUCCESS)) { + rc = env_open(env, 0); + if (unlikely(rc != MDBX_SUCCESS && env_close(env, false) != MDBX_SUCCESS)) { + rc = MDBX_PANIC; + env->me_flags |= MDBX_FATAL_ERROR; + } + } + return rc; +} +#endif /* Windows */ + __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { MDBX_page *dp; int rc = MDBX_SUCCESS; @@ -15834,7 +15871,7 @@ __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { } eASSERT(env, env->me_signature.weak == 0); - rc = env_close(env) ? MDBX_PANIC : rc; + rc = env_close(env, false) ? MDBX_PANIC : rc; ENSURE(env, osal_fastmutex_destroy(&env->me_dbi_lock) == MDBX_SUCCESS); #if defined(_WIN32) || defined(_WIN64) /* me_remap_guard don't have destructor (Slim Reader/Writer Lock) */