[runtime] Move pending_exception from InternalThread to Thread to avoid crashing...
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 16 Nov 2015 05:22:56 +0000 (00:22 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 11 Feb 2016 20:17:19 +0000 (15:17 -0500)
InternalThread is a fundamentally different type WRT to appdomain. All instances of Thread bound to the same
os thread have a reference to a shared InternalThread.

InternalThread is always allocated in the root domain, so it MUST NOT have references to other domains as
it will lead to crashes on unload.

This was the case with pending_exception. It could point to an exception meant to the domain unloading.

This bug became more and more frequent as we move to use mono_set_pending_exception in more places. I could
reproduce it in 10 minutes of looping appdomain-unload.exe.

mcs/class/corlib/System.Threading/Thread.cs
mcs/class/corlib/System/Environment.cs
mono/metadata/appdomain.c
mono/metadata/object-internals.h
mono/metadata/threads.c

index 7dcb5431760352cf6c2fee9bd2f5a0cafb235903..e10918121dd93fd162bf6452e72d8589d7d35908 100644 (file)
@@ -72,7 +72,6 @@ namespace System.Threading {
                /* current System.Runtime.Remoting.Contexts.Context instance
                   keep as an object to avoid triggering its class constructor when not needed */
                private object current_appcontext;
-               private object pending_exception;
                private object root_domain_thread;
                internal byte[] _serialized_principal;
                internal int _serialized_principal_version;
@@ -116,6 +115,7 @@ namespace System.Threading {
                #region Sync with metadata/object-internals.h
                private InternalThread internal_thread;
                object m_ThreadStartArg;
+               object pending_exception;
                #endregion
 #pragma warning restore 414
 
index 65e997caea328992309731feb3b9e51db7455eeb..44cdbe24d544f838940f057b4e9ef4ddd86847df 100644 (file)
@@ -57,7 +57,7 @@ namespace System {
                 * of icalls, do not require an increment.
                 */
 #pragma warning disable 169
-               private const int mono_corlib_version = 140;
+               private const int mono_corlib_version = 141;
 #pragma warning restore 169
 
                [ComVisible (true)]
index d618bef480307dc0ebc45309dc886a1bc2f82184..816a3e4180af15547281eec900b00eae4d285090 100644 (file)
@@ -80,7 +80,7 @@
  * Changes which are already detected at runtime, like the addition
  * of icalls, do not require an increment.
  */
-#define MONO_CORLIB_VERSION 140
+#define MONO_CORLIB_VERSION 141
 
 typedef struct
 {
index f694e4c7d0283fe32cc1d4ab2a7d888e2df5b905..45f93f157fa38747d06d25de3240c7eac1f9cb71 100644 (file)
@@ -409,7 +409,6 @@ struct _MonoInternalThread {
        gpointer *static_data;
        void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */
        MonoAppContext *current_appcontext;
-       MonoException *pending_exception;
        MonoThread *root_domain_thread;
        MonoObject *_serialized_principal;
        int _serialized_principal_version;
@@ -442,6 +441,7 @@ struct _MonoThread {
        MonoObject obj;
        struct _MonoInternalThread *internal_thread;
        MonoObject *start_obj;
+       MonoException *pending_exception;
 };
 
 typedef struct {
index 6867741e3ce39026918ea56b45a7c028cbe2e9a8..2eb4e4a4dbb648d67d37e738743c8a1a613d691b 100644 (file)
@@ -4325,6 +4325,7 @@ static MonoException*
 mono_thread_execute_interruption (void)
 {
        MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoThread *sys_thread = mono_thread_current ();
 
        LOCK_THREAD (thread);
 
@@ -4363,11 +4364,11 @@ mono_thread_execute_interruption (void)
                
                mono_thread_exit ();
                return NULL;
-       } else if (thread->pending_exception) {
+       } else if (sys_thread->pending_exception) {
                MonoException *exc;
 
-               exc = thread->pending_exception;
-               thread->pending_exception = NULL;
+               exc = sys_thread->pending_exception;
+               sys_thread->pending_exception = NULL;
 
         UNLOCK_THREAD (thread);
         return exc;
@@ -4519,6 +4520,7 @@ MonoException*
 mono_thread_get_and_clear_pending_exception (void)
 {
        MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoThread *sys_thread = mono_thread_current ();
 
        /* The thread may already be stopping */
        if (thread == NULL)
@@ -4528,10 +4530,10 @@ mono_thread_get_and_clear_pending_exception (void)
                return mono_thread_execute_interruption ();
        }
        
-       if (thread->pending_exception) {
-               MonoException *exc = thread->pending_exception;
+       if (sys_thread->pending_exception) {
+               MonoException *exc = sys_thread->pending_exception;
 
-               thread->pending_exception = NULL;
+               sys_thread->pending_exception = NULL;
                return exc;
        }
 
@@ -4547,7 +4549,7 @@ mono_thread_get_and_clear_pending_exception (void)
 void
 mono_set_pending_exception (MonoException *exc)
 {
-       MonoInternalThread *thread = mono_thread_internal_current ();
+       MonoThread *thread = mono_thread_current ();
 
        /* The thread may already be stopping */
        if (thread == NULL)