[threads] Fix leaking threads: SGen Worker and Finalizer (#5284)
authorArmin Hasitzka <cherusker@users.noreply.github.com>
Thu, 7 Sep 2017 10:23:07 +0000 (12:23 +0200)
committerBernhard Urban <bernhard.urban@xamarin.com>
Thu, 7 Sep 2017 10:23:07 +0000 (12:23 +0200)
* Fix leaking threads: SGen Worker and Finalizer
- https://bugzilla.xamarin.com/show_bug.cgi?id=58317
- stop SGen workers before the finalizer stops
- clean up SGen workers with the Finalizer
- remove `mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));` as we detach the Finalizer with `mono_threads_join_threads ()` within `mono_gc_cleanup ()`

* [fixup!] Move counting variable into the loop initialiser and add a `(gpointer)` cast

mono/metadata/gc.c
mono/sgen/sgen-thread-pool.c

index 4b1a56f4c0feeba858aca442d9e0ab057d7b1130..28b4747b27ee08f368cd2348b0eae02f0a4676eb 100644 (file)
@@ -973,6 +973,11 @@ 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;
@@ -995,7 +1000,8 @@ mono_gc_cleanup (void)
                                        ret = guarded_wait (gc_thread->handle, MONO_INFINITE_WAIT, FALSE);
                                        g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
 
-                                       mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
+                                       /* Clean up the finalizer (and other threads that might still wait to be joined) */
+                                       mono_threads_join_threads ();
                                        break;
                                }
 
@@ -1020,7 +1026,8 @@ mono_gc_cleanup (void)
 
                                        g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
 
-                                       mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
+                                       /* Clean up the finalizer (and other threads that might still wait to be joined) */
+                                       mono_threads_join_threads ();
                                        break;
                                }
 
@@ -1031,7 +1038,6 @@ mono_gc_cleanup (void)
                        }
                }
                gc_thread = NULL;
-               mono_gc_base_cleanup ();
        }
 
        mono_reference_queue_cleanup ();
index 211bc8b7277975471954dec78c7775c9a8e8c9f6..c9aaaa2667b5cb9b45cf5b7427f43e8a8bd96060 100644 (file)
@@ -305,6 +305,10 @@ sgen_thread_pool_shutdown (void)
        mono_os_mutex_destroy (&lock);
        mono_os_cond_destroy (&work_cond);
        mono_os_cond_destroy (&done_cond);
+
+       for (int i = 0; i < threads_num; i++) {
+               mono_threads_add_joinable_thread ((gpointer)threads [i]);
+       }
 }
 
 SgenThreadPoolJob*