diff --git a/src/api-env.c b/src/api-env.c index 498a224f..49884974 100644 --- a/src/api-env.c +++ b/src/api-env.c @@ -245,7 +245,8 @@ __cold int mdbx_env_create(MDBX_env **penv) { #if defined(_WIN32) || defined(_WIN64) imports.srwl_Init(&env->remap_guard); - InitializeCriticalSection(&env->windowsbug_lock); + InitializeCriticalSection(&env->lck_event_cs); + InitializeCriticalSection(&env->dxb_event_cs); #else rc = osal_fastmutex_init(&env->remap_guard); if (unlikely(rc != MDBX_SUCCESS)) { @@ -638,7 +639,8 @@ __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { ENSURE(env, osal_fastmutex_destroy(&env->dbi_lock) == MDBX_SUCCESS); #if defined(_WIN32) || defined(_WIN64) /* remap_guard don't have destructor (Slim Reader/Writer Lock) */ - DeleteCriticalSection(&env->windowsbug_lock); + DeleteCriticalSection(&env->lck_event_cs); + DeleteCriticalSection(&env->dxb_event_cs); #else ENSURE(env, osal_fastmutex_destroy(&env->remap_guard) == MDBX_SUCCESS); #endif /* Windows */ @@ -922,6 +924,7 @@ __cold int mdbx_preopen_snapinfoW(const wchar_t *pathname, MDBX_envinfo *out, si env.fd4meta = INVALID_HANDLE_VALUE; #if defined(_WIN32) || defined(_WIN64) env.dxb_lock_event = INVALID_HANDLE_VALUE; + env.lck_lock_event = INVALID_HANDLE_VALUE; env.ioring.overlapped_fd = INVALID_HANDLE_VALUE; #endif /* Windows */ env_options_init(&env); diff --git a/src/env.c b/src/env.c index 6fc5493f..2bcb0ad5 100644 --- a/src/env.c +++ b/src/env.c @@ -305,6 +305,12 @@ __cold int env_open(MDBX_env *env, mdbx_mode_t mode) { env->fd4meta = env->lazy_fd; #if defined(_WIN32) || defined(_WIN64) + env->dxb_lock_event = CreateEventW(nullptr, true, false, nullptr); + if (unlikely(!env->dxb_lock_event)) + return (int)GetLastError(); + env->lck_lock_event = CreateEventW(nullptr, true, false, nullptr); + if (unlikely(!env->lck_lock_event)) + return (int)GetLastError(); eASSERT(env, env->ioring.overlapped_fd == 0); bool ior_direct = false; if (!(env->flags & (MDBX_RDONLY | MDBX_SAFE_NOSYNC | MDBX_NOMETASYNC | MDBX_EXCLUSIVE))) { @@ -346,9 +352,6 @@ __cold int env_open(MDBX_env *env, mdbx_mode_t mode) { &env->ioring.overlapped_fd, 0); if (unlikely(rc != MDBX_SUCCESS)) return rc; - env->dxb_lock_event = CreateEventW(nullptr, true, false, nullptr); - if (unlikely(!env->dxb_lock_event)) - return (int)GetLastError(); osal_fseek(env->ioring.overlapped_fd, safe_parking_lot_offset); } #else @@ -545,6 +548,10 @@ __cold int env_close(MDBX_env *env, bool resurrect_after_fork) { CloseHandle(env->dxb_lock_event); env->dxb_lock_event = INVALID_HANDLE_VALUE; } + if (env->lck_lock_event != INVALID_HANDLE_VALUE) { + CloseHandle(env->lck_lock_event); + env->lck_lock_event = INVALID_HANDLE_VALUE; + } eASSERT(env, !resurrect_after_fork); if (env->pathname_char) { osal_free(env->pathname_char); diff --git a/src/internals.h b/src/internals.h index 4a3994d3..16d6b70b 100644 --- a/src/internals.h +++ b/src/internals.h @@ -352,6 +352,7 @@ struct MDBX_env { mdbx_filehandle_t dsync_fd, fd4meta; #if defined(_WIN32) || defined(_WIN64) HANDLE dxb_lock_event; + HANDLE lck_lock_event; #endif /* Windows */ osal_mmap_t lck_mmap; /* The lock file */ lck_t *lck; @@ -481,7 +482,8 @@ struct MDBX_env { #if defined(_WIN32) || defined(_WIN64) osal_srwlock_t remap_guard; /* Workaround for LockFileEx and WriteFile multithread bug */ - CRITICAL_SECTION windowsbug_lock; + CRITICAL_SECTION lck_event_cs; + CRITICAL_SECTION dxb_event_cs; char *pathname_char; /* cache of multi-byte representation of pathname to the DB files */ #else diff --git a/src/lck-windows.c b/src/lck-windows.c index f1499a32..f1c10b59 100644 --- a/src/lck-windows.c +++ b/src/lck-windows.c @@ -16,8 +16,11 @@ #define LCK_WAITFOR 0 #define LCK_DONTWAIT LOCKFILE_FAIL_IMMEDIATELY -static int flock_with_event(HANDLE fd, HANDLE event, unsigned flags, size_t offset, size_t bytes) { - TRACE("lock>>: fd %p, event %p, flags 0x%x offset %zu, bytes %zu >>", fd, event, flags, offset, bytes); +static int flock_ex(HANDLE fd, HANDLE event, unsigned flags, size_t offset, size_t bytes, unsigned timeout_ms) { + TRACE("lock>>: fd %p, timeout %u ms, event %p, flags 0x%x offset %zu, bytes %zu >>", fd, timeout_ms, event, flags, + offset, bytes); + assert(timeout_ms == 0 || (event && event != INVALID_HANDLE_VALUE)); + assert(timeout_ms == 0 || (flags & LCK_DONTWAIT) == 0); OVERLAPPED ov; ov.Internal = 0; ov.InternalHigh = 0; @@ -25,43 +28,43 @@ static int flock_with_event(HANDLE fd, HANDLE event, unsigned flags, size_t offs ov.Offset = (DWORD)offset; ov.OffsetHigh = HIGH_DWORD(offset); - int retry_left = (flags & LOCKFILE_FAIL_IMMEDIATELY) ? 3 : 0; - while (true) { - if (LockFileEx(fd, flags, 0, (DWORD)bytes, HIGH_DWORD(bytes), &ov)) { - TRACE("lock<<: fd %p, event %p, flags 0x%x offset %zu, bytes %zu << %s", fd, event, flags, offset, bytes, "done"); + if (LockFileEx(fd, flags, 0, (DWORD)bytes, HIGH_DWORD(bytes), &ov)) { + TRACE("lock<<: fd %p, timeout %u ms, event %p, flags 0x%x offset %zu, bytes %zu << %s", fd, timeout_ms, event, + flags, offset, bytes, "done"); + return MDBX_SUCCESS; + } + + DWORD rc = GetLastError(); + if (rc == ERROR_IO_PENDING) { + if (timeout_ms) { + rc = osal_waitstatus2errcode(WaitForSingleObject(event, timeout_ms)); + if (rc != MDBX_SUCCESS) { + if (rc == ERROR_TIMEOUT) + rc = ERROR_LOCK_VIOLATION; + goto bailout; + } + } + if (GetOverlappedResult(fd, &ov, &rc, true)) { + TRACE("lock<<: fd %p, timeout %u ms, event %p, flags 0x%x offset %zu, bytes %zu << %s", fd, timeout_ms, event, + flags, offset, bytes, "overlapped-done"); return MDBX_SUCCESS; } - - DWORD rc = GetLastError(); - if (rc == ERROR_IO_PENDING) { - if (event) { - if (GetOverlappedResult(fd, &ov, &rc, true)) { - TRACE("lock<<: fd %p, event %p, flags 0x%x offset %zu, bytes %zu << %s", fd, event, flags, offset, bytes, - "overlapped-done"); - return MDBX_SUCCESS; - } - rc = GetLastError(); - } else - CancelIo(fd); - } - - if (rc != ERROR_LOCK_VIOLATION || --retry_left < 1) { - TRACE("lock<<: fd %p, event %p, flags 0x%x offset %zu, bytes %zu << err %d", fd, event, flags, offset, bytes, - (int)rc); - return (int)rc; - } - - SleepEx(0, true); + bailout: + CancelIo(fd); } + + TRACE("lock<<: fd %p, timeout %u ms, event %p, flags 0x%x offset %zu, bytes %zu << err %d", fd, timeout_ms, event, + flags, offset, bytes, (int)rc); + return (int)rc; } -static inline int flock(HANDLE fd, unsigned flags, size_t offset, size_t bytes) { - return flock_with_event(fd, 0, flags, offset, bytes); +static int flock_lck(const MDBX_env *env, unsigned flags, size_t offset, size_t bytes, unsigned timeout_ms) { + return flock_ex(env->lck_mmap.fd, env->lck_lock_event, flags, offset, bytes, timeout_ms); } -static inline int flock_data(const MDBX_env *env, unsigned flags, size_t offset, size_t bytes) { +static int flock_dxb(const MDBX_env *env, unsigned flags, size_t offset, size_t bytes) { const HANDLE fd4data = env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd; - return flock_with_event(fd4data, env->dxb_lock_event, flags, offset, bytes); + return flock_ex(fd4data, env->dxb_lock_event, flags, offset, bytes, 0); } static int funlock(mdbx_filehandle_t fd, size_t offset, size_t bytes) { @@ -84,11 +87,11 @@ static int funlock(mdbx_filehandle_t fd, size_t offset, size_t bytes) { int lck_txn_lock(MDBX_env *env, bool dontwait) { if (dontwait) { - if (!TryEnterCriticalSection(&env->windowsbug_lock)) + if (!TryEnterCriticalSection(&env->dxb_event_cs)) return MDBX_BUSY; } else { __try { - EnterCriticalSection(&env->windowsbug_lock); + EnterCriticalSection(&env->dxb_event_cs); } __except ((GetExceptionCode() == 0xC0000194 /* STATUS_POSSIBLE_DEADLOCK / EXCEPTION_POSSIBLE_DEADLOCK */) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { @@ -100,34 +103,32 @@ int lck_txn_lock(MDBX_env *env, bool dontwait) { if (env->flags & MDBX_EXCLUSIVE) goto done; - const HANDLE fd4data = env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd; - int rc = flock_with_event(fd4data, env->dxb_lock_event, - dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT) : (LCK_EXCLUSIVE | LCK_WAITFOR), DXB_BODY); + int rc = flock_dxb(env, dontwait ? (LCK_EXCLUSIVE | LCK_DONTWAIT) : (LCK_EXCLUSIVE | LCK_WAITFOR), DXB_BODY); + if (rc == MDBX_SUCCESS) { done: if (env->basal_txn) env->basal_txn->owner = osal_thread_self(); - /* Zap: Failing to release lock 'env->windowsbug_lock' + /* Zap: Failing to release lock 'env->dxb_event_cs' * in function 'mdbx_txn_lock' */ MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return MDBX_SUCCESS; } - LeaveCriticalSection(&env->windowsbug_lock); + LeaveCriticalSection(&env->dxb_event_cs); return (!dontwait || rc != ERROR_LOCK_VIOLATION) ? rc : MDBX_BUSY; } void lck_txn_unlock(MDBX_env *env) { eASSERT(env, !env->basal_txn || env->basal_txn->owner == osal_thread_self()); if ((env->flags & MDBX_EXCLUSIVE) == 0) { - const HANDLE fd4data = env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd; - int err = funlock(fd4data, DXB_BODY); + int err = funlock(env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd, DXB_BODY); if (err != MDBX_SUCCESS) mdbx_panic("%s failed: err %u", __func__, err); } if (env->basal_txn) env->basal_txn->owner = 0; - LeaveCriticalSection(&env->windowsbug_lock); + LeaveCriticalSection(&env->dxb_event_cs); } /*----------------------------------------------------------------------------*/ @@ -142,19 +143,34 @@ void lck_txn_unlock(MDBX_env *env) { #define LCK_UPPER LCK_UP_OFFSET, LCK_UP_LEN int lck_rdt_lock(MDBX_env *env) { + int rc; imports.srwl_AcquireShared(&env->remap_guard); + + __try { + EnterCriticalSection(&env->lck_event_cs); + } __except ((GetExceptionCode() == 0xC0000194 /* STATUS_POSSIBLE_DEADLOCK / EXCEPTION_POSSIBLE_DEADLOCK */) + ? EXCEPTION_EXECUTE_HANDLER + : EXCEPTION_CONTINUE_SEARCH) { + rc = MDBX_EDEADLK; + goto bailout; + } + if (env->lck_mmap.fd == INVALID_HANDLE_VALUE) - return MDBX_SUCCESS; /* readonly database in readonly filesystem */ + goto done; /* readonly database in readonly filesystem */ /* transition from S-? (used) to S-E (locked), * e.g. exclusive lock upper-part */ if (env->flags & MDBX_EXCLUSIVE) - return MDBX_SUCCESS; + goto done; - int rc = flock(env->lck_mmap.fd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER); - if (rc == MDBX_SUCCESS) + rc = flock_lck(env, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER, 0); + if (rc == MDBX_SUCCESS) { + done: + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return MDBX_SUCCESS; + } +bailout: imports.srwl_ReleaseShared(&env->remap_guard); return rc; } @@ -166,11 +182,12 @@ void lck_rdt_unlock(MDBX_env *env) { if (err != MDBX_SUCCESS) mdbx_panic("%s failed: err %u", __func__, err); } + LeaveCriticalSection(&env->lck_event_cs); imports.srwl_ReleaseShared(&env->remap_guard); } int osal_lockfile(mdbx_filehandle_t fd, bool wait) { - return flock(fd, wait ? LCK_EXCLUSIVE | LCK_WAITFOR : LCK_EXCLUSIVE | LCK_DONTWAIT, 0, DXB_MAXLEN); + return flock_ex(fd, 0, wait ? LCK_EXCLUSIVE | LCK_WAITFOR : LCK_EXCLUSIVE | LCK_DONTWAIT, 0, DXB_MAXLEN, 0); } static int suspend_and_append(mdbx_handle_array_t **array, const DWORD ThreadId) { @@ -359,15 +376,18 @@ static void lck_unlock(MDBX_env *env) { } } +#define TIMEOUT_SHORT_MS 121 +#define TIMEOUT_LONG_MS 900000 /* 15 min */ + /* Seize state as 'exclusive-write' (E-E and returns MDBX_RESULT_TRUE) * or as 'used' (S-? and returns MDBX_RESULT_FALSE). * Otherwise returns an error. */ -static int internal_seize_lck(HANDLE lfd) { - assert(lfd != INVALID_HANDLE_VALUE); +static int internal_seize_lck(MDBX_env *env) { + assert(env->lck_mmap.fd != INVALID_HANDLE_VALUE); /* 1) now on ?-? (free), get ?-E (middle) */ jitter4testing(false); - int rc = flock(lfd, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER); + int rc = flock_lck(env, LCK_EXCLUSIVE | LCK_WAITFOR, LCK_UPPER, TIMEOUT_LONG_MS); if (rc != MDBX_SUCCESS) { /* 2) something went wrong, give up */; ERROR("%s, err %u", "?-?(free) >> ?-E(middle)", rc); @@ -376,7 +396,7 @@ static int internal_seize_lck(HANDLE lfd) { /* 3) now on ?-E (middle), try E-E (exclusive-write) */ jitter4testing(false); - rc = flock(lfd, LCK_EXCLUSIVE | LCK_DONTWAIT, LCK_LOWER); + rc = flock_lck(env, LCK_EXCLUSIVE, LCK_LOWER, TIMEOUT_SHORT_MS); if (rc == MDBX_SUCCESS) return MDBX_RESULT_TRUE /* 4) got E-E (exclusive-write), done */; @@ -384,7 +404,7 @@ static int internal_seize_lck(HANDLE lfd) { jitter4testing(false); if (rc != ERROR_SHARING_VIOLATION && rc != ERROR_LOCK_VIOLATION) { /* 6) something went wrong, give up */ - rc = funlock(lfd, LCK_UPPER); + rc = funlock(env->lck_mmap.fd, LCK_UPPER); if (rc != MDBX_SUCCESS) mdbx_panic("%s(%s) failed: err %u", __func__, "?-E(middle) >> ?-?(free)", rc); return rc; @@ -392,7 +412,7 @@ static int internal_seize_lck(HANDLE lfd) { /* 7) still on ?-E (middle), try S-E (locked) */ jitter4testing(false); - rc = flock(lfd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER); + rc = flock_lck(env, LCK_SHARED, LCK_LOWER, TIMEOUT_LONG_MS); jitter4testing(false); if (rc != MDBX_SUCCESS) @@ -400,7 +420,7 @@ static int internal_seize_lck(HANDLE lfd) { /* 8) now on S-E (locked) or still on ?-E (middle), * transition to S-? (used) or ?-? (free) */ - int err = funlock(lfd, LCK_UPPER); + int err = funlock(env->lck_mmap.fd, LCK_UPPER); if (err != MDBX_SUCCESS) mdbx_panic("%s(%s) failed: err %u", __func__, "X-E(locked/middle) >> X-?(used/free)", err); @@ -409,8 +429,6 @@ static int internal_seize_lck(HANDLE lfd) { } int lck_seize(MDBX_env *env) { - const HANDLE fd4data = env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd; - assert(fd4data != INVALID_HANDLE_VALUE); if (env->flags & MDBX_EXCLUSIVE) return MDBX_RESULT_TRUE /* nope since files were must be opened non-shareable */ @@ -419,13 +437,13 @@ int lck_seize(MDBX_env *env) { if (env->lck_mmap.fd == INVALID_HANDLE_VALUE) { /* LY: without-lck mode (e.g. on read-only filesystem) */ jitter4testing(false); - int rc = flock_data(env, LCK_SHARED | LCK_DONTWAIT, DXB_WHOLE); + int rc = flock_dxb(env, LCK_SHARED | LCK_DONTWAIT, DXB_WHOLE); if (rc != MDBX_SUCCESS) ERROR("%s, err %u", "without-lck", rc); return rc; } - int rc = internal_seize_lck(env->lck_mmap.fd); + int rc = internal_seize_lck(env); jitter4testing(false); if (rc == MDBX_RESULT_TRUE && (env->flags & MDBX_RDONLY) == 0) { /* Check that another process don't operates in without-lck mode. @@ -434,7 +452,7 @@ int lck_seize(MDBX_env *env) { * - we need an exclusive lock for do so; * - we can't lock meta-pages, otherwise other process could get an error * while opening db in valid (non-conflict) mode. */ - int err = flock_data(env, LCK_EXCLUSIVE | LCK_DONTWAIT, DXB_WHOLE); + int err = flock_dxb(env, LCK_EXCLUSIVE | LCK_DONTWAIT, DXB_WHOLE); if (err != MDBX_SUCCESS) { ERROR("%s, err %u", "lock-against-without-lck", err); jitter4testing(false); @@ -442,7 +460,7 @@ int lck_seize(MDBX_env *env) { return err; } jitter4testing(false); - err = funlock(fd4data, DXB_WHOLE); + err = funlock(env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd, DXB_WHOLE); if (err != MDBX_SUCCESS) mdbx_panic("%s(%s) failed: err %u", __func__, "unlock-against-without-lck", err); } @@ -451,9 +469,7 @@ int lck_seize(MDBX_env *env) { } int lck_downgrade(MDBX_env *env) { - const HANDLE fd4data = env->ioring.overlapped_fd ? env->ioring.overlapped_fd : env->lazy_fd; /* Transite from exclusive-write state (E-E) to used (S-?) */ - assert(fd4data != INVALID_HANDLE_VALUE); assert(env->lck_mmap.fd != INVALID_HANDLE_VALUE); if (env->flags & MDBX_EXCLUSIVE) @@ -465,7 +481,7 @@ int lck_downgrade(MDBX_env *env) { mdbx_panic("%s(%s) failed: err %u", __func__, "E-E(exclusive-write) >> ?-E(middle)", rc); /* 2) now at ?-E (middle), transition to S-E (locked) */ - rc = flock(env->lck_mmap.fd, LCK_SHARED | LCK_DONTWAIT, LCK_LOWER); + rc = flock_lck(env, LCK_SHARED, LCK_LOWER, TIMEOUT_LONG_MS); if (rc != MDBX_SUCCESS) { /* 3) something went wrong, give up */; ERROR("%s, err %u", "?-E(middle) >> S-E(locked)", rc); @@ -490,7 +506,7 @@ int lck_upgrade(MDBX_env *env, bool dont_wait) { /* 1) now on S-? (used), try S-E (locked) */ jitter4testing(false); - int rc = flock(env->lck_mmap.fd, dont_wait ? LCK_EXCLUSIVE | LCK_DONTWAIT : LCK_EXCLUSIVE, LCK_UPPER); + int rc = flock_lck(env, dont_wait ? LCK_EXCLUSIVE | LCK_DONTWAIT : LCK_EXCLUSIVE, LCK_UPPER, 0); if (rc != MDBX_SUCCESS) { /* 2) something went wrong, give up */; VERBOSE("%s, err %u", "S-?(used) >> S-E(locked)", rc); @@ -504,7 +520,7 @@ int lck_upgrade(MDBX_env *env, bool dont_wait) { /* 4) now on ?-E (middle), try E-E (exclusive-write) */ jitter4testing(false); - rc = flock(env->lck_mmap.fd, dont_wait ? LCK_EXCLUSIVE | LCK_DONTWAIT : LCK_EXCLUSIVE, LCK_LOWER); + rc = flock_lck(env, dont_wait ? LCK_EXCLUSIVE | LCK_DONTWAIT : LCK_EXCLUSIVE, LCK_LOWER, 0); if (rc != MDBX_SUCCESS) { /* 5) something went wrong, give up */; VERBOSE("%s, err %u", "?-E(middle) >> E-E(exclusive-write)", rc); diff --git a/src/osal.c b/src/osal.c index bd62a0c2..61f3d0ba 100644 --- a/src/osal.c +++ b/src/osal.c @@ -14,23 +14,6 @@ #include #endif -static int waitstatus2errcode(DWORD result) { - switch (result) { - case WAIT_OBJECT_0: - return MDBX_SUCCESS; - case WAIT_FAILED: - return (int)GetLastError(); - case WAIT_ABANDONED: - return ERROR_ABANDONED_WAIT_0; - case WAIT_IO_COMPLETION: - return ERROR_USER_APC; - case WAIT_TIMEOUT: - return ERROR_TIMEOUT; - default: - return ERROR_UNHANDLED_ERROR; - } -} - /* Map a result from an NTAPI call to WIN32 error code. */ static int ntstatus2errcode(NTSTATUS status) { DWORD dummy; @@ -420,7 +403,7 @@ int osal_condpair_destroy(osal_condpair_t *condpair) { int osal_condpair_lock(osal_condpair_t *condpair) { #if defined(_WIN32) || defined(_WIN64) DWORD code = WaitForSingleObject(condpair->mutex, INFINITE); - return waitstatus2errcode(code); + return osal_waitstatus2errcode(code); #else return osal_pthread_mutex_lock(&condpair->mutex); #endif @@ -450,7 +433,7 @@ int osal_condpair_wait(osal_condpair_t *condpair, bool part) { if (code == WAIT_OBJECT_0) return MDBX_SUCCESS; } - return waitstatus2errcode(code); + return osal_waitstatus2errcode(code); #else return pthread_cond_wait(&condpair->cond[part], &condpair->mutex); #endif @@ -1192,7 +1175,7 @@ int osal_openfile(const enum osal_openfile_purpose purpose, const MDBX_env *env, case MDBX_OPEN_LCK: CreationDisposition = OPEN_ALWAYS; DesiredAccess |= GENERIC_READ | GENERIC_WRITE; - FlagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY; + FlagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_OVERLAPPED; break; case MDBX_OPEN_DXB_READ: CreationDisposition = OPEN_EXISTING; @@ -1694,7 +1677,7 @@ int osal_thread_create(osal_thread_t *thread, THREAD_RESULT(THREAD_CALL *start_r int osal_thread_join(osal_thread_t thread) { #if defined(_WIN32) || defined(_WIN64) DWORD code = WaitForSingleObject(thread, INFINITE); - return waitstatus2errcode(code); + return osal_waitstatus2errcode(code); #else void *unused_retval = &unused_retval; return pthread_join(thread, &unused_retval); diff --git a/src/osal.h b/src/osal.h index 125834f0..50f0a500 100644 --- a/src/osal.h +++ b/src/osal.h @@ -206,6 +206,23 @@ typedef struct osal_mmap { #define MDBX_HAVE_PWRITEV 0 +static inline int osal_waitstatus2errcode(DWORD result) { + switch (result) { + case WAIT_OBJECT_0: + return MDBX_SUCCESS; + case WAIT_FAILED: + return (int)GetLastError(); + case WAIT_ABANDONED: + return ERROR_ABANDONED_WAIT_0; + case WAIT_IO_COMPLETION: + return ERROR_USER_APC; + case WAIT_TIMEOUT: + return ERROR_TIMEOUT; + default: + return ERROR_UNHANDLED_ERROR; + } +} + #elif defined(__ANDROID_API__) #if __ANDROID_API__ < 24 diff --git a/test/osal-windows.c++ b/test/osal-windows.c++ index 4a3f9e52..d7e643b8 100644 --- a/test/osal-windows.c++ +++ b/test/osal-windows.c++ @@ -9,32 +9,15 @@ static std::unordered_map events; static HANDLE hBarrierSemaphore, hBarrierEvent; static HANDLE hProgressActiveEvent, hProgressPassiveEvent; -static int waitstatus2errcode(DWORD result) { - switch (result) { - case WAIT_OBJECT_0: - return MDBX_SUCCESS; - case WAIT_FAILED: - return GetLastError(); - case WAIT_ABANDONED: - return ERROR_ABANDONED_WAIT_0; - case WAIT_IO_COMPLETION: - return ERROR_USER_APC; - case WAIT_TIMEOUT: - return ERROR_TIMEOUT; - default: - return ERROR_UNHANDLED_ERROR; - } -} - void osal_wait4barrier(void) { DWORD rc = WaitForSingleObject(hBarrierSemaphore, 0); switch (rc) { default: - failure_perror("WaitForSingleObject(BarrierSemaphore)", waitstatus2errcode(rc)); + failure_perror("WaitForSingleObject(BarrierSemaphore)", osal_waitstatus2errcode(rc)); case WAIT_OBJECT_0: rc = WaitForSingleObject(hBarrierEvent, INFINITE); if (rc != WAIT_OBJECT_0) - failure_perror("WaitForSingleObject(BarrierEvent)", waitstatus2errcode(rc)); + failure_perror("WaitForSingleObject(BarrierEvent)", osal_waitstatus2errcode(rc)); break; case WAIT_TIMEOUT: if (!SetEvent(hBarrierEvent)) @@ -95,7 +78,7 @@ void osal_broadcast(unsigned id) { int osal_waitfor(unsigned id) { log_trace("osal_waitfor: event %u", id); DWORD rc = WaitForSingleObject(events.at(id), INFINITE); - return waitstatus2errcode(rc); + return osal_waitstatus2errcode(rc); } int osal_delay(unsigned seconds) { @@ -397,7 +380,7 @@ int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { return 0; } - return waitstatus2errcode(rc); + return osal_waitstatus2errcode(rc); } } @@ -418,7 +401,7 @@ void osal_udelay(size_t us) { if (us > threshold_us && us > 1000) { DWORD rc = SleepEx(unsigned(us / 1000), TRUE); if (rc) - failure_perror("SleepEx()", waitstatus2errcode(rc)); + failure_perror("SleepEx()", osal_waitstatus2errcode(rc)); us = 0; }