Fix shutdown race between mono_thread_manage and mono_thread_detach_internal. (#5599)
[mono.git] / mono / utils / mono-threads-windows.c
index 2a28e9b5a13ab6fac7ed0e76c751e68101d43e48..563d210e8ed5cfe9ef657e7aba24d77d0f0429cf 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * mono-threads-windows.c: Low-level threading, windows version
+/**
+ * \file
+ * Low-level threading, windows version
  *
  * Author:
  *     Rodrigo Kumpera (kumpera@gmail.com)
 
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-threads-debug.h>
+#include <mono/utils/mono-os-wait.h>
 #include <limits.h>
 
-
 void
 mono_threads_suspend_init (void)
 {
 }
 
-static void CALLBACK
-interrupt_apc (ULONG_PTR param)
-{
-}
-
 gboolean
 mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
 {
@@ -56,9 +52,8 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru
        info->suspend_can_continue = mono_threads_get_runtime_callbacks ()->thread_state_init_from_handle (&info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], info);
        THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (void*)id, res);
        if (info->suspend_can_continue) {
-               //FIXME do we need to QueueUserAPC on this case?
                if (interrupt_kernel)
-                       QueueUserAPC ((PAPCFUNC)interrupt_apc, handle, (ULONG_PTR)NULL);
+                       mono_win32_interrupt_wait (info, handle, id);
        } else {
                THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (void*)info->native_handle, 0);
        }
@@ -73,11 +68,7 @@ mono_threads_suspend_check_suspend_result (MonoThreadInfo *info)
        return info->suspend_can_continue;
 }
 
-static void CALLBACK
-abort_apc (ULONG_PTR param)
-{
-       THREADS_INTERRUPT_DEBUG ("%06d - abort_apc () called", GetCurrentThreadId ());
-}
+
 
 void
 mono_threads_suspend_abort_syscall (MonoThreadInfo *info)
@@ -88,18 +79,11 @@ mono_threads_suspend_abort_syscall (MonoThreadInfo *info)
        handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id);
        g_assert (handle);
 
-       THREADS_INTERRUPT_DEBUG ("%06d - Aborting syscall in thread %06d", GetCurrentThreadId (), id);
-       QueueUserAPC ((PAPCFUNC)abort_apc, handle, (ULONG_PTR)NULL);
+       mono_win32_abort_wait (info, handle, id);
 
        CloseHandle (handle);
 }
 
-gboolean
-mono_threads_suspend_needs_abort_syscall (void)
-{
-       return TRUE;
-}
-
 gboolean
 mono_threads_suspend_begin_async_resume (MonoThreadInfo *info)
 {
@@ -189,22 +173,22 @@ mono_threads_suspend_get_abort_signal (void)
 
 #if defined (HOST_WIN32)
 
-int
-mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *out_tid)
+gboolean
+mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid)
 {
        HANDLE result;
        DWORD thread_id;
 
        result = CreateThread (NULL, stack_size ? *stack_size : 0, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id);
        if (!result)
-               return -1;
+               return FALSE;
 
        /* A new handle is open when attaching
         * the thread, so we don't need this one */
        CloseHandle (result);
 
-       if (out_tid)
-               *out_tid = thread_id;
+       if (tid)
+               *tid = thread_id;
 
        if (stack_size) {
                // TOOD: Use VirtualQuery to get correct value 
@@ -212,7 +196,7 @@ mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_
                *stack_size = 2 * 1024 * 1024;
        }
 
-       return 0;
+       return TRUE;
 }
 
 
@@ -234,19 +218,26 @@ mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
        return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL;
 }
 
+gboolean
+mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle)
+{
+       DWORD res = WaitForSingleObject (thread_handle, INFINITE);
+
+       if (close_handle)
+               CloseHandle (thread_handle);
+
+       return res != WAIT_FAILED;
+}
+
 gboolean
 mono_native_thread_join (MonoNativeThreadId tid)
 {
        HANDLE handle;
 
-       if (!(handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid)))
+       if (!(handle = OpenThread (SYNCHRONIZE, TRUE, tid)))
                return FALSE;
 
-       DWORD res = WaitForSingleObject (handle, INFINITE);
-
-       CloseHandle (handle);
-
-       return res != WAIT_FAILED;
+       return mono_native_thread_join_handle (handle, TRUE);
 }
 
 #if HAVE_DECL___READFSDWORD==0