[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