Fix sporadic hang in Mono.Debugger.Soft test suite on Windows.
[mono.git] / mono / metadata / gc.c
index 28b4747b27ee08f368cd2348b0eae02f0a4676eb..702857858eb25c4d50ca5485e92d32a91c37cd28 100644 (file)
@@ -44,6 +44,8 @@
 #include <mono/utils/mono-coop-semaphore.h>
 #include <mono/utils/hazard-pointer.h>
 #include <mono/utils/w32api.h>
+#include <mono/utils/unlocked.h>
+#include <mono/utils/mono-os-wait.h>
 
 #ifndef HOST_WIN32
 #include <pthread.h>
@@ -597,7 +599,7 @@ ves_icall_System_GC_WaitForPendingFinalizers (void)
        mono_gc_finalize_notify ();
        /* g_print ("Waiting for pending finalizers....\n"); */
        MONO_ENTER_GC_SAFE;
-       WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
+       mono_win32_wait_for_single_object_ex (pending_done_event, INFINITE, TRUE);
        MONO_EXIT_GC_SAFE;
        /* g_print ("Done pending....\n"); */
 #else
@@ -780,7 +782,7 @@ finalize_domain_objects (void)
        DomainFinalizationReq *req = NULL;
        MonoDomain *domain;
 
-       if (domains_to_finalize) {
+       if (UnlockedReadPointer ((gpointer)&domains_to_finalize)) {
                mono_finalizer_lock ();
                if (domains_to_finalize) {
                        req = (DomainFinalizationReq *)domains_to_finalize->data;
@@ -973,11 +975,6 @@ mono_gc_cleanup (void)
                return;
 
        if (!gc_disabled) {
-
-               /* Stop all worker threads before signalling the finalizer to stop
-                * That way the finalizer has a chance to clean up the worker threads */
-               mono_gc_base_cleanup ();
-
                finished = TRUE;
                if (mono_thread_internal_current () != gc_thread) {
                        int ret;
@@ -1000,8 +997,7 @@ mono_gc_cleanup (void)
                                        ret = guarded_wait (gc_thread->handle, MONO_INFINITE_WAIT, FALSE);
                                        g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
 
-                                       /* Clean up the finalizer (and other threads that might still wait to be joined) */
-                                       mono_threads_join_threads ();
+                                       mono_threads_add_joinable_thread (GUINT_TO_POINTER (gc_thread->tid));
                                        break;
                                }
 
@@ -1014,7 +1010,7 @@ mono_gc_cleanup (void)
                                        mono_gc_suspend_finalizers ();
 
                                        /* Try to abort the thread, in the hope that it is running managed code */
-                                       mono_thread_internal_abort (gc_thread);
+                                       mono_thread_internal_abort (gc_thread, FALSE);
 
                                        /* Wait for it to stop */
                                        ret = guarded_wait (gc_thread->handle, 100, FALSE);
@@ -1026,8 +1022,7 @@ mono_gc_cleanup (void)
 
                                        g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
 
-                                       /* Clean up the finalizer (and other threads that might still wait to be joined) */
-                                       mono_threads_join_threads ();
+                                       mono_threads_add_joinable_thread (GUINT_TO_POINTER (gc_thread->tid));
                                        break;
                                }
 
@@ -1038,6 +1033,7 @@ mono_gc_cleanup (void)
                        }
                }
                gc_thread = NULL;
+               mono_gc_base_cleanup ();
        }
 
        mono_reference_queue_cleanup ();