From eb4159ac8857a77040dbcc3113394f487eddafe3 Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Thu, 12 Sep 2019 00:49:10 +0300 Subject: [PATCH] mdbx-posix: support to close environment after fork() from a child process. Change-Id: I20ab9cf4525bfcacd10043e2afe7e1aa26a2af6c --- src/elements/core.c | 15 ++++++++++++++- src/elements/lck-posix.c | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/elements/core.c b/src/elements/core.c index 52ec3ff9..7765827e 100644 --- a/src/elements/core.c +++ b/src/elements/core.c @@ -763,7 +763,9 @@ static int lcklist_detach_locked(MDBX_env *env) { mdbx_ensure(env, env->me_lcklist_next == nullptr); } - rc = uniq_check(&env->me_lck_mmap, &inprocess_neighbor); + rc = likely(mdbx_getpid() == env->me_pid) + ? uniq_check(&env->me_lck_mmap, &inprocess_neighbor) + : MDBX_PANIC; if (!inprocess_neighbor && env->me_live_reader) (void)mdbx_rpid_clear(env); if (!MDBX_IS_ERROR(rc)) @@ -3157,6 +3159,17 @@ __cold static int mdbx_env_sync_ex(MDBX_env *env, int force, int nonblock) { if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) return MDBX_EBADSIGN; +#if MDBX_TXN_CHECKPID || !(defined(_WIN32) || defined(_WIN64)) + /* Check the PID even if MDBX_TXN_CHECKPID=0 on non-Windows + * platforms (i.e. where fork() is available). + * This is required to legitimize a call to mdbx_end_close() after fork() + * from a child process, that should be allowed to free resources. */ + if (unlikely(env->me_pid != mdbx_getpid())) { + env->me_flags |= MDBX_FATAL_ERROR; + return MDBX_PANIC; + } +#endif /* MDBX_TXN_CHECKPID */ + unsigned flags = env->me_flags & ~MDBX_NOMETASYNC; if (unlikely(flags & (MDBX_RDONLY | MDBX_FATAL_ERROR))) return MDBX_EACCESS; diff --git a/src/elements/lck-posix.c b/src/elements/lck-posix.c index 792ce75f..b6cd5766 100644 --- a/src/elements/lck-posix.c +++ b/src/elements/lck-posix.c @@ -176,6 +176,8 @@ static int lck_op(mdbx_filehandle_t fd, int cmd, int lck, off_t offset, MDBX_INTERNAL_FUNC int mdbx_rpid_set(MDBX_env *env) { assert(env->me_lfd != INVALID_HANDLE_VALUE); assert(env->me_pid > 0); + if (unlikely(mdbx_getpid() != env->me_pid)) + return MDBX_PANIC; return lck_op(env->me_lfd, op_setlk, F_WRLCK, env->me_pid, 1); } @@ -195,6 +197,8 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, mdbx_pid_t pid) { MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) { assert(env->me_fd != INVALID_HANDLE_VALUE); + if (unlikely(mdbx_getpid() != env->me_pid)) + return MDBX_PANIC; #if MDBX_USE_OFDLOCKS if (unlikely(op_setlk == 0)) choice_fcntl(); @@ -283,6 +287,9 @@ MDBX_INTERNAL_FUNC int __cold mdbx_lck_seize(MDBX_env *env) { MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env) { assert(env->me_lfd != INVALID_HANDLE_VALUE); + if (unlikely(mdbx_getpid() != env->me_pid)) + return MDBX_PANIC; + int rc = MDBX_SUCCESS; if ((env->me_flags & MDBX_EXCLUSIVE) == 0) { rc = lck_op(env->me_fd, op_setlk, F_UNLCK, 0, env->me_pid); @@ -301,6 +308,9 @@ MDBX_INTERNAL_FUNC int mdbx_lck_downgrade(MDBX_env *env) { MDBX_INTERNAL_FUNC int __cold mdbx_lck_destroy(MDBX_env *env, MDBX_env *inprocess_neighbor) { + if (unlikely(mdbx_getpid() != env->me_pid)) + return MDBX_PANIC; + int rc = MDBX_SUCCESS; if (env->me_lfd != INVALID_HANDLE_VALUE && !inprocess_neighbor && env->me_lck &&