Module: wine Branch: master Commit: 2bcc9d452a19f2d11ec4b3e655a3c4456b02cc96 URL: http://source.winehq.org/git/wine.git/?a=commit;h=2bcc9d452a19f2d11ec4b3e655...
Author: Piotr Caban piotr@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; }
/*********************************************************************