[runtime] Throw DomainUnloadedException exception when aborting appdomain thread
authorVlad Brezae <brezaevlad@gmail.com>
Thu, 14 Sep 2017 21:58:16 +0000 (00:58 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Fri, 22 Sep 2017 08:08:50 +0000 (11:08 +0300)
Before we were propagating the abort exception down in the calling domain.

mono/metadata/remoting.c
mono/tests/appdomain-unload.cs

index 7602c3926f41e685ee12030cdda08348fdebad46..dccb077b4f72cc41ccf1b0a47e9dee452794ad3d 100644 (file)
@@ -430,6 +430,7 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params)
 
        if (exc) {
                error_init (&error);
+               exc = (MonoObject*) mono_remoting_update_exception ((MonoException*)exc);
                mono_error_set_exception_instance (&error, (MonoException *)exc);
                goto fail;
        }
@@ -449,11 +450,18 @@ fail:
        return NULL;
 } 
 
+/*
+ * Handles exception transformation at appdomain call boundary.
+ * Note this is called from target appdomain inside xdomain wrapper, but from
+ * source domain in the mono_remoting_wrapper slowpath.
+ */
 static MonoException *
 mono_remoting_update_exception (MonoException *exc)
 {
+       MonoInternalThread *thread;
        MonoClass *klass = mono_object_get_class ((MonoObject*)exc);
 
+       /* Serialization error can only happen when still in the target appdomain */
        if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_SERIALIZABLE)) {
                MonoException *ret;
                char *aname = mono_stringify_assembly_name (&klass->image->assembly->aname);
@@ -464,6 +472,13 @@ mono_remoting_update_exception (MonoException *exc)
                return ret;
        }
 
+       thread = mono_thread_internal_current ();
+       if (mono_object_get_class ((MonoObject*)exc) == mono_defaults.threadabortexception_class &&
+                       thread->flags & MONO_THREAD_FLAG_APPDOMAIN_ABORT) {
+               mono_thread_internal_reset_abort (thread);
+               return mono_get_exception_appdomain_unloaded ();
+       }
+
        return exc;
 }
 
index e5ce63689219231bba99f26ef95eb35baafc8c1f..9d1790e16ff43bac799e9a30ad5a6143ee007a99 100644 (file)
@@ -240,15 +240,18 @@ public class Tests
 
        public static int test_0_unload_inside_appdomain_sync () {
                AppDomain domain = AppDomain.CreateDomain ("Test3");
+               bool caught = false;
 
                try {
                        domain.DoCallBack (new CrossAppDomainDelegate (SyncCallback));
                }
-               catch (Exception ex) {
-                       /* Should throw a ThreadAbortException */
-                       Thread.ResetAbort ();
+               catch (AppDomainUnloadedException ex) {
+                       caught = true;
                }
 
+               if (!caught)
+                       return 1;
+
                return 0;
        }