From fb50573d530838a8fa706568388272682e44e8f5 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 13 Jul 2016 17:19:36 +0200 Subject: [PATCH] [mono-threads] Create Win32 handle when attaching the thread This guarantee that a MonoThreadInfo always has a handle. --- mono/utils/mono-threads-posix.c | 43 ++++++++++++------------------- mono/utils/mono-threads-windows.c | 26 ++++++++++++++++--- mono/utils/mono-threads.c | 1 + mono/utils/mono-threads.h | 3 ++- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index cbf92bb1ce7..d8982e946aa 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -100,6 +100,13 @@ win32_priority_to_posix_priority (MonoThreadPriority priority, int policy) } } +void +mono_threads_platform_register (MonoThreadInfo *info) +{ + g_assert (!info->handle); + info->handle = thread_handle_create (); +} + typedef struct { void *(*start_routine)(void*); void *arg; @@ -118,21 +125,12 @@ inner_start_thread (void *arg) void *(*start_func)(void*) = start_info->start_routine; guint32 flags = start_info->flags; void *result; - HANDLE handle; MonoThreadInfo *info; - /* Register the thread with the io-layer */ - handle = thread_handle_create (); - if (!handle) { - mono_coop_sem_post (&(start_info->registered)); - return NULL; - } - start_info->handle = handle; - info = mono_thread_info_attach (&result); - info->runtime_thread = TRUE; - info->handle = handle; + + start_info->handle = info->handle; mono_threads_platform_set_priority (info, start_info->priority); @@ -250,14 +248,10 @@ mono_threads_platform_yield (void) void mono_threads_platform_exit (int exit_code) { - MonoThreadInfo *current = mono_thread_info_current (); - #if defined(__native_client__) nacl_shutdown_gc_thread(); #endif - mono_threads_platform_set_exited (current); - mono_thread_info_detach (); pthread_exit (NULL); @@ -266,10 +260,7 @@ mono_threads_platform_exit (int exit_code) void mono_threads_platform_unregister (MonoThreadInfo *info) { - if (info->handle) { - mono_threads_platform_set_exited (info); - info->handle = NULL; - } + mono_threads_platform_set_exited (info); } HANDLE @@ -279,11 +270,10 @@ mono_threads_platform_open_handle (void) info = mono_thread_info_current (); g_assert (info); + g_assert (info->handle); + + mono_w32handle_ref (info->handle); - if (!info->handle) - info->handle = thread_handle_create (); - else - mono_w32handle_ref (info->handle); return info->handle; } @@ -406,7 +396,9 @@ mono_threads_platform_set_exited (MonoThreadInfo *info) pid_t pid; pthread_t tid; - if (!info->handle || mono_w32handle_issignalled (info->handle) || mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED) { + g_assert (info->handle); + + if (mono_w32handle_issignalled (info->handle) || mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED) { /* We must have already deliberately finished * with this thread, so don't do any more now */ return; @@ -630,9 +622,6 @@ mono_threads_suspend_register (MonoThreadInfo *info) #if defined (PLATFORM_ANDROID) info->native_handle = gettid (); #endif - - g_assert (!info->handle); - info->handle = thread_handle_create (); } void diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index b926791f062..f64f5743ce5 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -121,8 +121,6 @@ mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) void mono_threads_suspend_register (MonoThreadInfo *info) { - g_assert (!info->handle); - info->handle = mono_threads_platform_open_handle(); } void @@ -134,6 +132,22 @@ mono_threads_suspend_free (MonoThreadInfo *info) #if defined (HOST_WIN32) +void +mono_threads_platform_register (MonoThreadInfo *info) +{ + HANDLE thread_handle; + + thread_handle = GetCurrentThread (); + g_assert (thread_handle); + + /* The handle returned by GetCurrentThread () is a pseudo handle, so it can't + * be used to refer to the thread from other threads for things like aborting. */ + DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0); + + g_assert (!info->handle); + info->handle = thread_handle; +} + typedef struct { LPTHREAD_START_ROUTINE start_routine; void *arg; @@ -141,6 +155,7 @@ typedef struct { MonoCoopSem registered; gboolean suspend; HANDLE suspend_event; + HANDLE handle; } ThreadStartInfo; static DWORD WINAPI @@ -148,7 +163,6 @@ inner_start_thread (LPVOID arg) { ThreadStartInfo *start_info = arg; void *t_arg = start_info->arg; - int post_result; LPTHREAD_START_ROUTINE start_func = start_info->start_routine; DWORD result; gboolean suspend = start_info->suspend; @@ -159,6 +173,8 @@ inner_start_thread (LPVOID arg) info->runtime_thread = TRUE; info->create_suspended = suspend; + start_info->handle = info->handle; + mono_threads_platform_set_priority(info, start_info->priority); mono_coop_sem_post (&(start_info->registered)); @@ -204,6 +220,10 @@ mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg res = mono_coop_sem_wait (&(start_info->registered), MONO_SEM_FLAGS_NONE); g_assert (res != -1); + /* A new handle has been opened when attaching + * the thread, so we don't need this one */ + CloseHandle (result); + if (start_info->suspend) { g_assert (SuspendThread (result) != (DWORD)-1); SetEvent (start_info->suspend_event); diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index 33796525b90..456bb97ea9d 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -373,6 +373,7 @@ register_thread (MonoThreadInfo *info, gpointer baseptr) info->stackdata = g_byte_array_new (); + mono_threads_platform_register (info); mono_threads_suspend_register (info); /* diff --git a/mono/utils/mono-threads.h b/mono/utils/mono-threads.h index 6e74ec9fb8a..15841081f67 100644 --- a/mono/utils/mono-threads.h +++ b/mono/utils/mono-threads.h @@ -536,12 +536,13 @@ void mono_threads_suspend_free (THREAD_INFO_TYPE *info); void mono_threads_suspend_abort_syscall (THREAD_INFO_TYPE *info); gboolean mono_threads_suspend_needs_abort_syscall (void); +void mono_threads_platform_register (THREAD_INFO_TYPE *info); +void mono_threads_platform_unregister (THREAD_INFO_TYPE *info); HANDLE mono_threads_platform_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *, MonoNativeThreadId *out_tid); void mono_threads_platform_resume_created (THREAD_INFO_TYPE *info, MonoNativeThreadId tid); void mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize); gboolean mono_threads_platform_yield (void); void mono_threads_platform_exit (int exit_code); -void mono_threads_platform_unregister (THREAD_INFO_TYPE *info); HANDLE mono_threads_platform_open_handle (void); HANDLE mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid); void mono_threads_platform_set_exited (THREAD_INFO_TYPE *info); -- 2.25.1