From 164ba0d2042e10817b45b56e413a49419870841a Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Mon, 13 Sep 2010 08:09:01 -0300 Subject: [PATCH] Fix a sgen shutdown crash. * threads.c (mono_thread_suspend_all_other_threads): wait_data must not be malloc'd since it holds managed pointers. Alloc it on stack since the struct is about 512/1024 bytes long. * threads.c (mono_thread_manage): Ditto. * threads.c (mono_threads_request_thread_dump): Ditto. --- mono/metadata/threads.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 9b5e2881a84..11b18a00b6d 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -2981,8 +2981,10 @@ mono_threads_is_shutting_down (void) void mono_thread_manage (void) { - struct wait_data *wait=g_new0 (struct wait_data, 1); + struct wait_data wait_data; + struct wait_data *wait = &wait_data; + memset (wait, 0, sizeof (struct wait_data)); /* join each thread that's still running */ THREAD_DEBUG (g_message ("%s: Joining each running thread...", __func__)); @@ -2990,7 +2992,6 @@ void mono_thread_manage (void) if(threads==NULL) { THREAD_DEBUG (g_message("%s: No threads", __func__)); mono_threads_unlock (); - g_free (wait); return; } mono_threads_unlock (); @@ -3007,6 +3008,8 @@ void mono_thread_manage (void) ResetEvent (background_change_event); wait->num=0; + /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/ + memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P); mono_g_hash_table_foreach (threads, build_wait_tids, wait); mono_threads_unlock (); if(wait->num>0) { @@ -3033,6 +3036,8 @@ void mono_thread_manage (void) mono_threads_lock (); wait->num = 0; + /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/ + memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P); mono_g_hash_table_foreach_remove (threads, remove_and_abort_threads, wait); mono_threads_unlock (); @@ -3052,8 +3057,6 @@ void mono_thread_manage (void) #ifndef HOST_WIN32 sched_yield (); #endif - - g_free (wait); } static void terminate_thread (gpointer key, gpointer value, gpointer user) @@ -3114,13 +3117,15 @@ collect_threads_for_suspend (gpointer key, gpointer value, gpointer user_data) */ void mono_thread_suspend_all_other_threads (void) { - struct wait_data *wait = g_new0 (struct wait_data, 1); + struct wait_data wait_data; + struct wait_data *wait = &wait_data; int i; gsize self = GetCurrentThreadId (); gpointer *events; guint32 eventidx = 0; gboolean starting, finished; + memset (wait, 0, sizeof (struct wait_data)); /* * The other threads could be in an arbitrary state at this point, i.e. * they could be starting up, shutting down etc. This means that there could be @@ -3147,6 +3152,8 @@ void mono_thread_suspend_all_other_threads (void) * threads while threads_mutex is held. */ wait->num = 0; + /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/ + memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P); mono_threads_lock (); mono_g_hash_table_foreach (threads, collect_threads_for_suspend, wait); mono_threads_unlock (); @@ -3243,8 +3250,6 @@ void mono_thread_suspend_all_other_threads (void) g_free (events); } - - g_free (wait); } static void @@ -3273,9 +3278,12 @@ collect_threads (gpointer key, gpointer value, gpointer user_data) void mono_threads_request_thread_dump (void) { - struct wait_data *wait = g_new0 (struct wait_data, 1); + struct wait_data wait_data; + struct wait_data *wait = &wait_data; int i; + memset (wait, 0, sizeof (struct wait_data)); + /* * Make a copy of the hashtable since we can't do anything with * threads while threads_mutex is held. -- 2.11.4.GIT