mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:24:13 +08:00
mdbx-windows: workaround for Windows10 bugs.
This resolves https://github.com/leo-yuriev/libmdbx/issues/47
This commit is contained in:
parent
c2f850b566
commit
718f997502
@ -226,12 +226,19 @@ static int suspend_and_append(mdbx_handle_array_t **array,
|
||||
(*array)->limit = limit * 2;
|
||||
}
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ThreadId);
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
|
||||
FALSE, ThreadId);
|
||||
if (hThread == NULL)
|
||||
return GetLastError();
|
||||
|
||||
if (SuspendThread(hThread) == -1) {
|
||||
int err = GetLastError();
|
||||
DWORD ExitCode;
|
||||
if (err == /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED ||
|
||||
!GetExitCodeThread(hThread, &ExitCode) || ExitCode != STILL_ACTIVE)
|
||||
err = MDBX_SUCCESS;
|
||||
CloseHandle(hThread);
|
||||
return GetLastError();
|
||||
return err;
|
||||
}
|
||||
|
||||
(*array)->handles[(*array)->count++] = hThread;
|
||||
@ -316,9 +323,15 @@ int mdbx_suspend_threads_before_remap(MDBX_env *env,
|
||||
int mdbx_resume_threads_after_remap(mdbx_handle_array_t *array) {
|
||||
int rc = MDBX_SUCCESS;
|
||||
for (unsigned i = 0; i < array->count; ++i) {
|
||||
if (ResumeThread(array->handles[i]) == -1)
|
||||
rc = GetLastError();
|
||||
CloseHandle(array->handles[i]);
|
||||
const HANDLE hThread = array->handles[i];
|
||||
if (ResumeThread(hThread) == -1) {
|
||||
const int err = GetLastError();
|
||||
DWORD ExitCode;
|
||||
if (err != /* workaround for Win10 UCRT bug */ ERROR_ACCESS_DENIED &&
|
||||
GetExitCodeThread(hThread, &ExitCode) && ExitCode == STILL_ACTIVE)
|
||||
rc = err;
|
||||
}
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
72
src/mdbx.c
72
src/mdbx.c
@ -2295,18 +2295,20 @@ bailout:
|
||||
VALGRIND_CREATE_BLOCK(env->me_map, env->me_mapsize, "mdbx");
|
||||
}
|
||||
#endif
|
||||
} else if (rc != MDBX_RESULT_TRUE) {
|
||||
mdbx_error("failed resize datafile/mapping: "
|
||||
"present %" PRIuPTR " -> %" PRIuPTR ", "
|
||||
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
|
||||
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
|
||||
rc);
|
||||
} else {
|
||||
mdbx_notice("unable resize datafile/mapping: "
|
||||
"present %" PRIuPTR " -> %" PRIuPTR ", "
|
||||
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
|
||||
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper, limit_bytes,
|
||||
rc);
|
||||
if (rc != MDBX_RESULT_TRUE) {
|
||||
mdbx_error("failed resize datafile/mapping: "
|
||||
"present %" PRIuPTR " -> %" PRIuPTR ", "
|
||||
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
|
||||
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper,
|
||||
limit_bytes, rc);
|
||||
} else {
|
||||
mdbx_notice("unable resize datafile/mapping: "
|
||||
"present %" PRIuPTR " -> %" PRIuPTR ", "
|
||||
"limit %" PRIuPTR " -> %" PRIuPTR ", errcode %d",
|
||||
env->me_dbgeo.now, size_bytes, env->me_dbgeo.upper,
|
||||
limit_bytes, rc);
|
||||
}
|
||||
if (!env->me_dxb_mmap.address) {
|
||||
env->me_flags |= MDBX_FATAL_ERROR;
|
||||
if (env->me_txn)
|
||||
@ -3161,6 +3163,16 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
||||
rc = mdbx_rdt_lock(env);
|
||||
if (unlikely(MDBX_IS_ERROR(rc)))
|
||||
return rc;
|
||||
if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) {
|
||||
mdbx_rdt_unlock(env);
|
||||
return MDBX_PANIC;
|
||||
}
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (unlikely(!env->me_map)) {
|
||||
mdbx_rdt_unlock(env);
|
||||
return MDBX_EPERM;
|
||||
}
|
||||
#endif /* Windows */
|
||||
rc = MDBX_SUCCESS;
|
||||
|
||||
if (unlikely(env->me_live_reader != env->me_pid)) {
|
||||
@ -3259,6 +3271,16 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
||||
rc = mdbx_txn_lock(env, F_ISSET(flags, MDBX_TRYTXN));
|
||||
if (unlikely(rc))
|
||||
return rc;
|
||||
if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) {
|
||||
mdbx_txn_unlock(env);
|
||||
return MDBX_PANIC;
|
||||
}
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (unlikely(!env->me_map)) {
|
||||
mdbx_txn_unlock(env);
|
||||
return MDBX_EPERM;
|
||||
}
|
||||
#endif /* Windows */
|
||||
|
||||
mdbx_jitter4testing(false);
|
||||
MDBX_meta *meta = mdbx_meta_head(env);
|
||||
@ -3318,8 +3340,11 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
||||
goto bailout;
|
||||
}
|
||||
rc = mdbx_mapresize(env, txn->mt_end_pgno, upper_pgno);
|
||||
if (rc != MDBX_SUCCESS)
|
||||
if (rc != MDBX_SUCCESS) {
|
||||
if (rc == MDBX_RESULT_TRUE)
|
||||
rc = MDBX_MAP_RESIZED;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
txn->mt_owner = mdbx_thread_self();
|
||||
return MDBX_SUCCESS;
|
||||
@ -3367,6 +3392,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
||||
if (unlikely(!env || !ret))
|
||||
return MDBX_EINVAL;
|
||||
|
||||
*ret = NULL;
|
||||
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
|
||||
return MDBX_EBADSIGN;
|
||||
|
||||
@ -3376,8 +3402,12 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
||||
if (unlikely(env->me_flags & MDBX_FATAL_ERROR))
|
||||
return MDBX_PANIC;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
/* Don't check env->me_map until lock to avoid race with re-mapping for
|
||||
* shrinking */
|
||||
if (unlikely(!env->me_map))
|
||||
return MDBX_EPERM;
|
||||
#endif /* Windows */
|
||||
|
||||
flags &= MDBX_TXN_BEGIN_FLAGS;
|
||||
flags |= env->me_flags & MDBX_WRITEMAP;
|
||||
@ -3388,16 +3418,21 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
||||
|
||||
if (parent) {
|
||||
if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE))
|
||||
return MDBX_EINVAL;
|
||||
return MDBX_EBADSIGN;
|
||||
|
||||
if (unlikely(parent->mt_owner != mdbx_thread_self()))
|
||||
return MDBX_THREAD_MISMATCH;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (unlikely(!env->me_map))
|
||||
return MDBX_EPERM;
|
||||
#endif /* Windows */
|
||||
|
||||
/* Nested transactions: Max 1 child, write txns only, no writemap */
|
||||
flags |= parent->mt_flags;
|
||||
if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) {
|
||||
if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED)))
|
||||
return (parent->mt_flags & MDBX_TXN_RDONLY) ? MDBX_EINVAL : MDBX_BAD_TXN;
|
||||
}
|
||||
|
||||
/* Child txns save MDBX_pgstate and use own copy of cursors */
|
||||
size = env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + 1);
|
||||
size += tsize = sizeof(MDBX_ntxn);
|
||||
@ -3475,10 +3510,11 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
||||
rc = mdbx_txn_renew0(txn, flags);
|
||||
}
|
||||
|
||||
if (unlikely(rc)) {
|
||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||
if (txn != env->me_txn0)
|
||||
mdbx_free(txn);
|
||||
} else {
|
||||
mdbx_assert(env, (txn->mt_flags & ~MDBX_RDONLY) == 0);
|
||||
txn->mt_signature = MDBX_MT_SIGNATURE;
|
||||
*ret = txn;
|
||||
mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO
|
||||
@ -4859,8 +4895,10 @@ int mdbx_txn_commit(MDBX_txn *txn) {
|
||||
rc = mdbx_sync_locked(
|
||||
env, env->me_flags | txn->mt_flags | MDBX_SHRINK_ALLOWED, &meta);
|
||||
}
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||
env->me_flags |= MDBX_FATAL_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (likely(env->me_lck))
|
||||
env->me_lck->mti_readers_refresh_flag = false;
|
||||
|
10
src/osal.c
10
src/osal.c
@ -1071,11 +1071,11 @@ int mdbx_mresize(int flags, mdbx_mmap_t *map, size_t size, size_t limit) {
|
||||
&ReservedSize, MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ReservedAddress = NULL;
|
||||
if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 ||
|
||||
limit == map->length)
|
||||
if (status != /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018)
|
||||
goto bailout_ntstatus /* no way to recovery */;
|
||||
|
||||
/* assume we can change base address if mapping size changed */
|
||||
/* assume we can change base address if mapping size changed or prev address
|
||||
* couldn't be used */
|
||||
map->address = NULL;
|
||||
}
|
||||
|
||||
@ -1132,8 +1132,8 @@ retry_mapview:;
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (status == /* STATUS_CONFLICTING_ADDRESSES */ 0xC0000018 &&
|
||||
map->address && limit != map->length) {
|
||||
/* try remap at another base address, but only if the limit is changing */
|
||||
map->address) {
|
||||
/* try remap at another base address */
|
||||
map->address = NULL;
|
||||
goto retry_mapview;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user