From b8610e3e690eac3a1fd53aadc3b0a11a7aed5b6f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Sun, 18 Jan 2009 01:35:54 +0000 Subject: [PATCH] 2009-01-16 Zoltan Varga Backport of r123642. * threads.c (mono_threads_abort_appdomain_threads): Abort threads outside the threads_lock () to prevent deadlocks. svn path=/branches/mono-2-2/mono/; revision=123723 --- mono/metadata/ChangeLog | 7 +++++++ mono/metadata/threads.c | 15 ++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 340c6a4291d..5ccf9cf0674 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,10 @@ +2009-01-16 Zoltan Varga + + Backport of r123642. + + * threads.c (mono_threads_abort_appdomain_threads): Abort threads outside the + threads_lock () to prevent deadlocks. + 2009-01-13 Zoltan Varga Backport of r123201. diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 17f56971ac3..72354bf4d6d 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -2993,7 +2993,7 @@ typedef struct abort_appdomain_data { } abort_appdomain_data; static void -abort_appdomain_thread (gpointer key, gpointer value, gpointer user_data) +collect_appdomain_thread (gpointer key, gpointer value, gpointer user_data) { MonoThread *thread = (MonoThread*)value; abort_appdomain_data *data = (abort_appdomain_data*)user_data; @@ -3002,8 +3002,6 @@ abort_appdomain_thread (gpointer key, gpointer value, gpointer user_data) if (mono_thread_has_appdomain_ref (thread, domain)) { /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */ - ves_icall_System_Threading_Thread_Abort (thread, NULL); - if(data->wait.numtid); if (handle == NULL) @@ -3030,6 +3028,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) abort_appdomain_data user_data; guint32 start_time; int orig_timeout = timeout; + int i; THREAD_DEBUG (g_message ("%s: starting abort", __func__)); @@ -3039,15 +3038,21 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) user_data.domain = domain; user_data.wait.num = 0; - mono_g_hash_table_foreach (threads, abort_appdomain_thread, &user_data); + /* This shouldn't take any locks */ + mono_g_hash_table_foreach (threads, collect_appdomain_thread, &user_data); mono_threads_unlock (); - if (user_data.wait.num > 0) + if (user_data.wait.num > 0) { + /* Abort the threads outside the threads lock */ + for (i = 0; i < user_data.wait.num; ++i) + ves_icall_System_Threading_Thread_Abort (user_data.wait.threads [i], NULL); + /* * We should wait for the threads either to abort, or to leave the * domain. We can't do the latter, so we wait with a timeout. */ wait_for_tids (&user_data.wait, 100); + } /* Update remaining time */ timeout -= mono_msec_ticks () - start_time; -- 2.25.1