[mono-threads] Create Win32 handle when attaching the thread
authorLudovic Henry <ludovic@xamarin.com>
Wed, 13 Jul 2016 15:19:36 +0000 (17:19 +0200)
committerLudovic Henry <ludovic@xamarin.com>
Wed, 24 Aug 2016 14:39:17 +0000 (16:39 +0200)
This guarantee that a MonoThreadInfo always has a handle.

mono/utils/mono-threads-posix.c
mono/utils/mono-threads-windows.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index cbf92bb1ce763ee726ca92b17688d746d38089d2..d8982e946aafaeb4d0048be10650abcfe36cd32b 100644 (file)
@@ -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
index b926791f0621f7dd5e0a57dba29569ae6b10815a..f64f5743ce55ad188e4552b6fc6d4422927e6f26 100644 (file)
@@ -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);
index 33796525b90bec8fca74b00d013382cf4eec6398..456bb97ea9d5f6f9fe0a1803230d8540e58d7457 100644 (file)
@@ -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);
 
        /*
index 6e74ec9fb8aa0ef95f5dbabcb429cc35dd680f24..15841081f675511cb87ae1b5e35a542c11070f7b 100644 (file)
@@ -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);