#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
}
}
- free (messages);
+ g_free (messages);
return g_string_free (text, FALSE);
#else
return g_strdup ("");
}
}
+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 ();
+}