[runtime] Move mono_invoke_unhandled_exception_hook to metadata
authorAleksey Kliger <aleksey@xamarin.com>
Fri, 29 Jul 2016 16:55:35 +0000 (12:55 -0400)
committerAleksey Kliger <aleksey@xamarin.com>
Fri, 29 Jul 2016 16:55:35 +0000 (12:55 -0400)
And call it consistently in thread start functions when the managed
thread start function returns with an exception.

(If coop is not enabled, the exception handler unwinds the thread and
when there's no handler invokes the unhandled exception hook via
jit_tls->abort_func, so this is just for the coop case.)

Fixes mono/tests/unhandled-exception-1.cs for coop and bitcode.

mono/metadata/exception.c
mono/metadata/exception.h
mono/metadata/threads.c
mono/mini/driver.c
mono/mini/mini-exceptions.c
mono/mini/mini-llvm.c
mono/mini/mini.h

index 2aff26dfd53788fe5080ef51e97cbaf0b9975045..e9ebcf38d384ca945bae7903c53e1658fee3691e 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <glib.h>
 #include <config.h>
+#include <mono/metadata/environment.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/exception-internals.h>
 
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <string.h>
 
 #ifdef HAVE_EXECINFO_H
 #include <execinfo.h>
 #endif
 
+static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
+static gpointer unhandled_exception_hook_data = NULL;
+
 /**
  * mono_exception_from_name:
  * @image: the Mono image where to look for the class
@@ -1051,3 +1056,50 @@ mono_error_set_pending_exception (MonoError *error)
        }
 }
 
+void
+mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
+{
+       unhandled_exception_hook = func;
+       unhandled_exception_hook_data = user_data;
+}
+
+void
+mono_invoke_unhandled_exception_hook (MonoObject *exc)
+{
+       if (unhandled_exception_hook) {
+               unhandled_exception_hook (exc, unhandled_exception_hook_data);
+       } else {
+               MonoError inner_error;
+               MonoObject *other = NULL;
+               MonoString *str = mono_object_try_to_string (exc, &other, &inner_error);
+               char *msg = NULL;
+               
+               if (str && is_ok (&inner_error)) {
+                       msg = mono_string_to_utf8_checked (str, &inner_error);
+               }
+               if (!is_ok (&inner_error)) {
+                       msg = g_strdup_printf ("Nested exception while formatting original exception");
+                       mono_error_cleanup (&inner_error);
+               } else if (other) {
+                       char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
+                       char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
+
+                       msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
+                               original_backtrace, nested_backtrace);
+
+                       g_free (original_backtrace);
+                       g_free (nested_backtrace);
+               } else {
+                       msg = g_strdup ("Nested exception trying to figure out what went wrong");
+               }
+               mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
+               g_free (msg);
+#if defined(HOST_IOS)
+               g_assertion_message ("Terminating runtime due to unhandled exception");
+#else
+               exit (mono_environment_exitcode_get ());
+#endif
+       }
+
+       g_assert_not_reached ();
+}
index 3de5ae7ff57681981cf95a766105308ab2cacc79..895a67795fab27df7a2d7e7e1e98e100dbb6ad3c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _MONO_METADATA_EXCEPTION_H_
 #define _MONO_METADATA_EXCEPTION_H_
 
+#include <glib.h>
 #include <mono/metadata/object.h>
 #include <mono/metadata/image.h>
 
@@ -147,6 +148,14 @@ MONO_RT_EXTERNAL_ONLY
 MONO_API MonoException *
 mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception);
 
+/* Installs a function which is called when the runtime encounters an unhandled exception.
+ * This hook isn't expected to return.
+ * If no hook has been installed, the runtime will print a message before aborting.
+ */
+typedef void  (*MonoUnhandledExceptionFunc)         (MonoObject *exc, gpointer user_data);
+MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data);
+void          mono_invoke_unhandled_exception_hook  (MonoObject *exc);
+
 MONO_END_DECLS
 
 #endif /* _MONO_METADATA_EXCEPTION_H_ */
index 523b5188cc5a5edb22fae1514edec68a6a49b79d..447989d1ebc5b38c08bf25995b9d3c170f246fc4 100644 (file)
@@ -748,8 +748,11 @@ static guint32 WINAPI start_wrapper_internal(void *data)
 
                if (!mono_error_ok (&error)) {
                        MonoException *ex = mono_error_convert_to_exception (&error);
-                       if (ex)
+                       if (ex) {
                                mono_unhandled_exception (&ex->object);
+                               mono_invoke_unhandled_exception_hook (&ex->object);
+                               g_assert_not_reached ();
+                       }
                } else {
                        mono_error_cleanup (&error);
                }
@@ -5068,6 +5071,7 @@ mono_thread_internal_unhandled_exception (MonoObject* exc)
                        mono_thread_internal_reset_abort (mono_thread_internal_current ());
                } else if (!is_appdomainunloaded_exception (klass)) {
                        mono_unhandled_exception (exc);
+                       // AK: Should we call mono_invoke_unhandled_exception_hook here?
                        if (mono_environment_exitcode_get () == 1)
                                exit (255);
                }
index aba82d5ffcb99b4112210194768ec78050379d33..9181e53b25257183de08774b3a793327ebe33be2 100644 (file)
@@ -1033,15 +1033,18 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[
                if (exc) {
                        mono_unhandled_exception (exc);
                        mono_invoke_unhandled_exception_hook (exc);
-                       return 1;
+                       g_assert_not_reached ();
                }
                return res;
        } else {
                int res = mono_runtime_run_main_checked (method, argc, argv, &error);
                if (!is_ok (&error)) {
                        MonoException *ex = mono_error_convert_to_exception (&error);
-                       if (ex)
-                               mono_unhandled_exception ((MonoObject*)ex);
+                       if (ex) {
+                               mono_unhandled_exception (&ex->object);
+                               mono_invoke_unhandled_exception_hook (&ex->object);
+                               g_assert_not_reached ();
+                       }
                }
                return res;
        }
index 4030fb08384971855e3a7687813fb8ff7686e105..9c375a9aee767a3d055b8926db1cdf440d15f8ca 100644 (file)
@@ -89,9 +89,6 @@ static gpointer throw_corlib_exception_func;
 static gpointer try_more_restore_tramp = NULL;
 static gpointer restore_stack_protection_tramp = NULL;
 
-static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
-static gpointer unhandled_exception_hook_data = NULL;
-
 static void try_more_restore (void);
 static void restore_stack_protection (void);
 static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data);
@@ -2824,54 +2821,6 @@ mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpoint
 #endif
 }
 
-void
-mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
-{
-       unhandled_exception_hook = func;
-       unhandled_exception_hook_data = user_data;
-}
-
-void
-mono_invoke_unhandled_exception_hook (MonoObject *exc)
-{
-       if (unhandled_exception_hook) {
-               unhandled_exception_hook (exc, unhandled_exception_hook_data);
-       } else {
-               MonoError inner_error;
-               MonoObject *other = NULL;
-               MonoString *str = mono_object_try_to_string (exc, &other, &inner_error);
-               char *msg = NULL;
-               
-               if (str && is_ok (&inner_error)) {
-                       msg = mono_string_to_utf8_checked (str, &inner_error);
-               }
-               if (!is_ok (&inner_error)) {
-                       msg = g_strdup_printf ("Nested exception while formatting original exception");
-                       mono_error_cleanup (&inner_error);
-               } else if (other) {
-                       char *original_backtrace = mono_exception_get_managed_backtrace ((MonoException*)exc);
-                       char *nested_backtrace = mono_exception_get_managed_backtrace ((MonoException*)other);
-
-                       msg = g_strdup_printf ("Nested exception detected.\nOriginal Exception: %s\nNested exception:%s\n",
-                               original_backtrace, nested_backtrace);
-
-                       g_free (original_backtrace);
-                       g_free (nested_backtrace);
-               } else {
-                       msg = g_strdup ("Nested exception trying to figure out what went wrong");
-               }
-               mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
-               g_free (msg);
-#if defined(HOST_IOS)
-               g_assertion_message ("Terminating runtime due to unhandled exception");
-#else
-               exit (mono_environment_exitcode_get ());
-#endif
-       }
-
-       g_assert_not_reached ();
-}
-
 /*
  * mono_restore_context:
  *
index 6031df370c283e4be3816e4640b24b6528739bb4..e08765758f495716906462e84f10a42f9bbafc3b 100644 (file)
@@ -9034,6 +9034,7 @@ default_mono_llvm_unhandled_exception (void)
        MonoObject *target = mono_gchandle_get_target (jit_tls->thrown_exc);
 
        mono_unhandled_exception (target);
+       // AK: should we call mono_invoke_unhandled_exception_hook here?
        exit (mono_environment_exitcode_get ());
 }
 
index 21e8e62ad3793b8cd67db09a88a89d20f81c403a..bafaa414969ec65fa1aafd1bfbcaaa7da7307102 100644 (file)
@@ -2866,14 +2866,6 @@ MonoBoolean ves_icall_get_frame_info            (gint32 skip, MonoBoolean need_f
                                                 MonoString **file, gint32 *line, gint32 *column);
 void mono_set_cast_details                      (MonoClass *from, MonoClass *to);
 
-/* Installs a function which is called when the runtime encounters an unhandled exception.
- * This hook isn't expected to return.
- * If no hook has been installed, the runtime will print a message before aborting.
- */
-typedef void  (*MonoUnhandledExceptionFunc)         (MonoObject *exc, gpointer user_data);
-MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data);
-void          mono_invoke_unhandled_exception_hook  (MonoObject *exc);
-
 void mono_decompose_typechecks (MonoCompile *cfg);
 /* Dominator/SSA methods */
 void        mono_compile_dominator_info         (MonoCompile *cfg, int dom_flags);