Add an unhandled exception hook embedders can use to report unhandled exceptions...
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Thu, 15 Mar 2012 09:24:09 +0000 (10:24 +0100)
committerRolf Bjarne Kvinge <rolf@xamarin.com>
Mon, 10 Sep 2012 21:50:03 +0000 (23:50 +0200)
mono/mini/mini-exceptions.c
mono/mini/mini.c
mono/mini/mini.h

index 362b18aff33ead5bbb798b1587eb66f41cb56b68..def6f2c655e20e7f1b5d684848aa331f65ca797d 100644 (file)
@@ -45,6 +45,7 @@
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/mono-endian.h>
+#include <mono/metadata/environment.h>
 #include <mono/utils/mono-mmap.h>
 
 #include "mini.h"
@@ -63,6 +64,9 @@ 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);
@@ -2642,3 +2646,31 @@ mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpoint
        g_error ("This target doesn't support mono_arch_setup_async_callback");
 #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 {
+               MonoObject *other = NULL;
+               MonoString *str = mono_object_to_string (exc, &other);
+               if (str) {
+                       char *msg = mono_string_to_utf8 (str);
+                       fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
+                       fflush (stderr);
+                       g_free (msg);
+               }
+
+               exit (mono_environment_exitcode_get ());
+       }
+
+       g_assert_not_reached ();
+}
index f881c5bdbe502c56d37bd43ebc57181167d97ba4..5f429ce81331438e2e1c40ae29d8296b82f38150 100644 (file)
@@ -2666,16 +2666,7 @@ mono_thread_abort (MonoObject *obj)
                        (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
                mono_thread_exit ();
        } else {
-               MonoObject *other = NULL;
-               MonoString *str = mono_object_to_string (obj, &other);
-               if (str) {
-                       char *msg = mono_string_to_utf8 (str);
-                       fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg);
-                       fflush (stderr);
-                       g_free (msg);
-               }
-
-               exit (mono_environment_exitcode_get ());
+               mono_invoke_unhandled_exception_hook (obj);
        }
 }
 
index af08dc43fdc9a243ab2f0462c5f178c8b284c144..498ba5aa201901ad476815130e835906789683e8 100644 (file)
@@ -2241,6 +2241,14 @@ MonoBoolean ves_icall_get_frame_info            (gint32 skip, MonoBoolean need_f
 MonoString *ves_icall_System_Exception_get_trace (MonoException *exc) MONO_INTERNAL;
 void mono_set_cast_details                      (MonoClass *from, MonoClass *to) MONO_INTERNAL;
 
+/* 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);
+void          mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data);
+void          mono_invoke_unhandled_exception_hook  (MonoObject *exc);
+
 /* Dominator/SSA methods */
 void        mono_compile_dominator_info         (MonoCompile *cfg, int dom_flags) MONO_INTERNAL;
 void        mono_compute_natural_loops          (MonoCompile *cfg) MONO_INTERNAL;