[runtime] Don't terminate application on unhandled AppDomainUnloadedException
authorVlad Brezae <brezaevlad@gmail.com>
Thu, 14 Sep 2017 23:34:26 +0000 (02:34 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Fri, 22 Sep 2017 08:08:50 +0000 (11:08 +0300)
Except for threads started by unmanaged code (like the main thread).

mono/metadata/class-internals.h
mono/metadata/loader.c
mono/metadata/object.c
mono/metadata/threads.c
mono/mini/mini-runtime.c

index 2b3a0b42aa31a9359c2bd01ed41803e6beda8942..f744fc1fdc4c66144ab648e52b7f9f0160953c40 100644 (file)
@@ -1170,6 +1170,8 @@ GENERATE_GET_CLASS_WITH_CACHE_DECL (variant)
 
 #endif
 
+GENERATE_GET_CLASS_WITH_CACHE_DECL (appdomain_unloaded_exception)
+
 extern MonoDefaults mono_defaults;
 
 void
index 5281a5d39b882e00e1a16c5dc39c23ce1aa22bf8..a5ef34da2d6e5901cd3c2e704b90bb3fdeeeb3b6 100644 (file)
@@ -76,6 +76,9 @@ MonoNativeTlsKey loader_lock_nest_id;
 static void dllmap_cleanup (void);
 static void cached_module_cleanup(void);
 
+/* Class lazy loading functions */
+GENERATE_GET_CLASS_WITH_CACHE (appdomain_unloaded_exception, "System", "AppDomainUnloadedException")
+
 static void
 global_loader_data_lock (void)
 {
index 2ea88c75f8cfde20ecb362453f027e16dbe1225a..9ace3f66652855063c4af180e32252fb48708dc2 100644 (file)
@@ -4587,7 +4587,14 @@ mono_unhandled_exception_checked (MonoObjectHandle exc, MonoError *error)
        MonoObjectHandle current_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, NULL);
 
        MonoClass *klass = mono_handle_class (exc);
-       if (mono_class_has_parent (klass, mono_defaults.threadabortexception_class))
+       /*
+        * AppDomainUnloadedException don't behave like unhandled exceptions unless thrown from 
+        * a thread started in unmanaged world.
+        * https://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(v=vs.110).aspx#Anchor_6
+        */
+       if (klass == mono_defaults.threadabortexception_class ||
+                       (klass == mono_class_get_appdomain_unloaded_exception_class () &&
+                       mono_thread_info_current ()->runtime_thread))
                return;
 
        field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "UnhandledException");
index f804fce27933f6565bdb532785e2ba2be895cf3e..52dc0c0c23001fa962b2fe7e74dd8afe53a5de48 100644 (file)
@@ -199,9 +199,6 @@ static gboolean shutting_down = FALSE;
 
 static gint32 managed_thread_id_counter = 0;
 
-/* Class lazy loading functions */
-static GENERATE_GET_CLASS_WITH_CACHE (appdomain_unloaded_exception, "System", "AppDomainUnloadedException")
-
 static void
 mono_threads_lock (void)
 {
index 5e6e3cd9cad8ea865617bc9fcc4e078b1ce46db2..90d695ae2d63a1028762ac33317db4a9c4f1c541 100644 (file)
@@ -890,7 +890,9 @@ mono_thread_abort (MonoObject *obj)
        g_free (jit_tls);*/
 
        if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_LEGACY) ||
-                       (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
+                       (obj->vtable->klass == mono_defaults.threadabortexception_class) ||
+                       ((obj->vtable->klass) == mono_class_get_appdomain_unloaded_exception_class () &&
+                       mono_thread_info_current ()->runtime_thread)) {
                mono_thread_exit ();
        } else {
                mono_invoke_unhandled_exception_hook (obj);