mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-11-01 03:48:57 +08:00 
			
		
		
		
	mdbx-windows: workaround for Windows10 bugs.
This resolves https://github.com/leo-yuriev/libmdbx/issues/47
This commit is contained in:
		| @@ -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; | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user