[PATCH 3/4] msvcrt: Make UCRT _beginthread[ex]() hold the DLL reference.
Arkadiusz Hiler
ahiler at codeweavers.com
Mon May 3 08:07:17 CDT 2021
MSVCRT _beginthread[ex]() doesn't exhibit the same behavior.
Using ThreadExit() does leak the reference.
FreeLibraryAndExit() has to be used because the DLL may be the only user
of the given CRT.
Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
---
dlls/msvcrt/msvcrt.h | 1 +
dlls/msvcrt/thread.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 8f6ee08ef2a..c84e0a0a638 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -167,6 +167,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 523e463d695..b796f7ac852 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,7 +79,13 @@ void CDECL _endthread(void)
} else
WARN("tls=%p tls->handle=%p\n", tls, tls ? tls->handle : INVALID_HANDLE_VALUE);
- /* FIXME */
+#if _MSVCR_VER >= 140
+ if (tls && tls->module != NULL)
+ FreeLibraryAndExitThread(tls->module, 0);
+ else
+ WARN("tls=%p tls->module=%p\n", tls, tls ? tls->module : NULL);
+#endif
+
ExitThread(0);
}
@@ -88,7 +97,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 +123,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();
return 0;
@@ -160,6 +188,18 @@ static DWORD CALLBACK _beginthreadex_trampoline(LPVOID arg)
memcpy(&local_trampoline,arg,sizeof(local_trampoline));
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);
--
2.31.1
More information about the wine-devel
mailing list