Arkadiusz Hiler : msvcrt: Make UCRT _beginthread[ex]() hold the DLL reference.
Alexandre Julliard
julliard at winehq.org
Wed May 5 16:09:01 CDT 2021
Module: wine
Branch: master
Commit: 7435ca85453079283da43d716fac48aa1bf5ca3f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7435ca85453079283da43d716fac48aa1bf5ca3f
Author: Arkadiusz Hiler <ahiler at codeweavers.com>
Date: Wed May 5 13:03:12 2021 +0300
msvcrt: Make UCRT _beginthread[ex]() hold the DLL reference.
MSVCRT's _beginthread[ex]() doesn't exhibit the same behavior and using
ThreadExit() does leak the reference.
FreeLibraryAndExit() has to be used because the DLL may be the only user
of the given CRT.
This fixes Baldur's Gate 3 crashing shortly after launch.
Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcrt/msvcrt.h | 1 +
dlls/msvcrt/thread.c | 39 ++++++++++++++++++++++++++++++++++++---
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 669d8c29a98..ad366a74d86 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -168,6 +168,7 @@ struct __thread_data {
void *unk10[100];
#if _MSVCR_VER >= 140
_invalid_parameter_handler invalid_parameter_handler;
+ HMODULE module;
#endif
};
diff --git a/dlls/msvcrt/thread.c b/dlls/msvcrt/thread.c
index d342d57d38c..01500d93d91 100644
--- a/dlls/msvcrt/thread.c
+++ b/dlls/msvcrt/thread.c
@@ -54,6 +54,9 @@ thread_data_t *CDECL msvcrt_get_thread_data(void)
ptr->random_seed = 1;
ptr->locinfo = MSVCRT_locale->locinfo;
ptr->mbcinfo = MSVCRT_locale->mbcinfo;
+#if _MSVCR_VER >= 140
+ ptr->module = NULL;
+#endif
}
SetLastError( err );
return ptr;
@@ -76,8 +79,7 @@ void CDECL _endthread(void)
} else
WARN("tls=%p tls->handle=%p\n", tls, tls ? tls->handle : INVALID_HANDLE_VALUE);
- /* FIXME */
- ExitThread(0);
+ _endthreadex(0);
}
/*********************************************************************
@@ -88,7 +90,17 @@ void CDECL _endthreadex(
{
TRACE("(%d)\n", retval);
- /* FIXME */
+#if _MSVCR_VER >= 140
+ {
+ thread_data_t *tls = TlsGetValue(msvcrt_tls_index);
+
+ if (tls && tls->module != NULL)
+ FreeLibraryAndExitThread(tls->module, retval);
+ else
+ WARN("tls=%p tls->module=%p\n", tls, tls ? tls->module : NULL);
+ }
+#endif
+
ExitThread(retval);
}
@@ -104,6 +116,15 @@ static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
data->handle = local_trampoline.thread;
free(arg);
+#if _MSVCR_VER >= 140
+ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (void*)local_trampoline.start_address, &data->module))
+ {
+ data->module = NULL;
+ WARN("failed to get module for the start_address: %d\n", GetLastError());
+ }
+#endif
+
local_trampoline.start_address(local_trampoline.arglist);
_endthread();
}
@@ -163,6 +184,18 @@ static DWORD CALLBACK _beginthreadex_trampoline(LPVOID arg)
data->handle = local_trampoline.thread;
free(arg);
+#if _MSVCR_VER >= 140
+ {
+ thread_data_t *data = msvcrt_get_thread_data();
+ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ (void*)local_trampoline.start_address_ex, &data->module))
+ {
+ data->module = NULL;
+ WARN("failed to get module for the start_address: %d\n", GetLastError());
+ }
+ }
+#endif
+
retval = local_trampoline.start_address_ex(local_trampoline.arglist);
_endthreadex(retval);
}
More information about the wine-cvs
mailing list