Fix a sgen shutdown crash.
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 13 Sep 2010 11:09:01 +0000 (08:09 -0300)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 13 Sep 2010 11:11:55 +0000 (08:11 -0300)
* 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

index edbc22173be928392253ec9ece0e6c9570f8cd70..4a66b03f3d108bd5bcb774de61a86abf20c5cdd8 100644 (file)
@@ -2995,8 +2995,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__));
        
@@ -3004,7 +3006,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 ();
@@ -3021,6 +3022,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) {
@@ -3047,6 +3050,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 ();
@@ -3066,8 +3071,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)
@@ -3128,13 +3131,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
@@ -3161,6 +3166,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 ();
@@ -3257,8 +3264,6 @@ void mono_thread_suspend_all_other_threads (void)
 
                g_free (events);
        }
-
-       g_free (wait);
 }
 
 static void
@@ -3287,9 +3292,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.