mdbx-posix: support to close environment after fork() from a child process.

Change-Id: I20ab9cf4525bfcacd10043e2afe7e1aa26a2af6c
This commit is contained in:
Leonid Yuriev 2019-09-12 00:49:10 +03:00
parent 4b979826ec
commit eb4159ac88
2 changed files with 24 additions and 1 deletions

View File

@ -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;

View File

@ -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 &&