Piotr Caban : msvcrt: Close thread handle when _beginthread is used.

Alexandre Julliard julliard at winehq.org
Wed May 25 11:28:12 CDT 2011


Module: wine
Branch: master
Commit: 2bcc9d452a19f2d11ec4b3e655a3c4456b02cc96
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2bcc9d452a19f2d11ec4b3e655a3c4456b02cc96

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue May 24 17:22:02 2011 +0200

msvcrt: Close thread handle when _beginthread is used.

---

 dlls/msvcrt/main.c   |    1 +
 dlls/msvcrt/msvcrt.h |    2 +
 dlls/msvcrt/thread.c |   59 ++++++++++++++++++++++++++++++++++---------------
 3 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c
index cca6189..f1ef67b 100644
--- a/dlls/msvcrt/main.c
+++ b/dlls/msvcrt/main.c
@@ -66,6 +66,7 @@ static inline void msvcrt_free_tls_mem(void)
   thread_data_t *tls = TlsGetValue(msvcrt_tls_index);
   if (tls)
   {
+    CloseHandle(tls->handle);
     HeapFree(GetProcessHeap(),0,tls->efcvt_buffer);
     HeapFree(GetProcessHeap(),0,tls->asctime_buffer);
     HeapFree(GetProcessHeap(),0,tls->wasctime_buffer);
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 31fe719..8fc3b03 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -107,6 +107,8 @@ struct MSVCRT_tm {
 extern DWORD msvcrt_tls_index;
 
 struct __thread_data {
+    DWORD                           tid;
+    HANDLE                          handle;
     int                             thread_errno;
     MSVCRT_ulong                    thread_doserrno;
     unsigned int                    random_seed;        /* seed for rand() */
diff --git a/dlls/msvcrt/thread.c b/dlls/msvcrt/thread.c
index dc6edcd..2afb183 100644
--- a/dlls/msvcrt/thread.c
+++ b/dlls/msvcrt/thread.c
@@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 /********************************************************************/
 
 typedef struct {
+  HANDLE is_ready, thread;
   MSVCRT__beginthread_start_routine_t start_address;
   void *arglist;
 } _beginthread_trampoline_t;
@@ -44,6 +45,8 @@ thread_data_t *msvcrt_get_thread_data(void)
         if (!(ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptr) )))
             _amsg_exit( _RT_THREAD );
         if (!TlsSetValue( msvcrt_tls_index, ptr )) _amsg_exit( _RT_THREAD );
+        ptr->tid = GetCurrentThreadId();
+        ptr->handle = INVALID_HANDLE_VALUE;
         ptr->random_seed = 1;
     }
     SetLastError( err );
@@ -56,13 +59,19 @@ thread_data_t *msvcrt_get_thread_data(void)
  */
 static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
 {
-    _beginthread_trampoline_t local_trampoline;
+    _beginthread_trampoline_t local_trampoline, *trampoline = arg;
+    thread_data_t *data = msvcrt_get_thread_data();
+
+    if(!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
+            &trampoline->thread, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+        trampoline->thread = NULL;
+        SetEvent(&trampoline->is_ready);
+        return 0;
+    }
 
-    /* Maybe it's just being paranoid, but freeing arg right
-     * away seems safer.
-     */
-    memcpy(&local_trampoline,arg,sizeof(local_trampoline));
-    MSVCRT_free(arg);
+    memcpy(&local_trampoline, trampoline, sizeof(local_trampoline));
+    data->handle = local_trampoline.thread;
+    SetEvent(trampoline->is_ready);
 
     local_trampoline.start_address(local_trampoline.arglist);
     return 0;
@@ -76,21 +85,35 @@ MSVCRT_uintptr_t CDECL _beginthread(
   unsigned int stack_size, /* [in] Stack size for new thread or 0 */
   void *arglist)           /* [in] Argument list to be passed to new thread or NULL */
 {
-  _beginthread_trampoline_t* trampoline;
+  _beginthread_trampoline_t trampoline;
+  HANDLE thread;
 
   TRACE("(%p, %d, %p)\n", start_address, stack_size, arglist);
 
-  /* Allocate the trampoline here so that it is still valid when the thread
-   * starts... typically after this function has returned.
-   * _beginthread_trampoline is responsible for freeing the trampoline
-   */
-  trampoline=MSVCRT_malloc(sizeof(*trampoline));
-  trampoline->start_address = start_address;
-  trampoline->arglist = arglist;
-
-  /* FIXME */
-  return (MSVCRT_uintptr_t)CreateThread(NULL, stack_size, _beginthread_trampoline,
-				     trampoline, 0, NULL);
+  trampoline.is_ready = CreateEventW(NULL, FALSE, FALSE, NULL);
+  if(!trampoline.is_ready) {
+      *MSVCRT__errno() = MSVCRT_EAGAIN;
+      return -1;
+  }
+  trampoline.start_address = start_address;
+  trampoline.arglist = arglist;
+
+  thread = CreateThread(NULL, stack_size, _beginthread_trampoline,
+          &trampoline, 0, NULL);
+  if(!thread) {
+      *MSVCRT__errno() = MSVCRT_EAGAIN;
+      return -1;
+  }
+  CloseHandle(thread);
+
+  WaitForSingleObject(trampoline.is_ready, INFINITE);
+  CloseHandle(trampoline.is_ready);
+
+  if(!trampoline.thread) {
+      *MSVCRT__errno() = MSVCRT_EAGAIN;
+      return -1;
+  }
+  return (MSVCRT_uintptr_t)trampoline.thread;
 }
 
 /*********************************************************************




More information about the wine-cvs mailing list