*/
#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
const char *name, MonoString *a1, MonoString *a2)
{
MonoError error;
- MonoClass *klass;
MonoException *ret;
- klass = mono_class_load_from_name (image, name_space, name);
+ ret = mono_exception_from_name_two_strings_checked (image, name_space, name, a1, a2, &error);
+ mono_error_cleanup (&error);
+ return ret;
+}
+
+/**
+ * mono_exception_from_name_two_strings_checked:
+ * @image: the Mono image where to look for the class
+ * @name_space: the namespace for the class
+ * @name: class name
+ * @a1: first string argument to pass
+ * @a2: second string argument to pass
+ * @error: set on error
+ *
+ * Creates an exception from a constructor that takes two string
+ * arguments.
+ *
+ * Returns: the initialized exception instance. On failure returns
+ * NULL and sets @error.
+ */
+MonoException *
+mono_exception_from_name_two_strings_checked (MonoImage *image, const char *name_space,
+ const char *name, MonoString *a1, MonoString *a2,
+ MonoError *error)
+{
+ MonoClass *klass;
- ret = create_exception_two_strings (klass, a1, a2, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_error_init (error);
+ klass = mono_class_load_from_name (image, name_space, name);
- return ret;
+ return create_exception_two_strings (klass, a1, a2, error);
}
/**
MonoString *a1, MonoString *a2)
{
MonoError error;
- MonoClass *klass;
MonoException *ret;
+ ret = mono_exception_from_token_two_strings_checked (image, token, a1, a2, &error);
+ mono_error_cleanup (&error);
+ return ret;
+}
- klass = mono_class_get_checked (image, token, &error);
- mono_error_assert_ok (&error); /* FIXME handle the error. */
+/**
+ * mono_exception_from_token_two_strings_checked:
+ *
+ * Same as mono_exception_from_name_two_strings, but lookup the exception class using
+ * IMAGE and TOKEN.
+ */
+MonoException *
+mono_exception_from_token_two_strings_checked (MonoImage *image, guint32 token,
+ MonoString *a1, MonoString *a2,
+ MonoError *error)
+{
+ MonoClass *klass;
- ret = create_exception_two_strings (klass, a1, a2, &error);
- mono_error_raise_exception (&error); /* FIXME don't raise here */
+ mono_error_init (error);
- return ret;
+ klass = mono_class_get_checked (image, token, error);
+ mono_error_assert_ok (error); /* FIXME handle the error. */
+
+ return create_exception_two_strings (klass, a1, a2, error);
}
/**
{
MonoString *s = assembly_name ? mono_string_new (mono_domain_get (), assembly_name) : mono_string_new (mono_domain_get (), "");
- return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
- "TypeLoadException", class_name, s);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
+ "TypeLoadException", class_name, s, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
- return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
- "MissingMethodException", s1, s2);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
+ "MissingMethodException", s1, s2, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
MonoString *s1 = mono_string_new (mono_domain_get (), class_name);
MonoString *s2 = mono_string_new (mono_domain_get (), member_name);
- return mono_exception_from_name_two_strings (mono_get_corlib (), "System",
- "MissingFieldException", s1, s2);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System",
+ "MissingFieldException", s1, s2, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
MonoException *
mono_get_exception_file_not_found (MonoString *fname)
{
- return mono_exception_from_name_two_strings (
- mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (
+ mono_get_corlib (), "System.IO", "FileNotFoundException", fname, fname, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
{
MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
- return mono_exception_from_name_two_strings (
- mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (
+ mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
{
MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL;
- return mono_exception_from_name_two_strings (
- mono_get_corlib (), "System", "BadImageFormatException", s, fname);
+ MonoError error;
+ MonoException *ret = mono_exception_from_name_two_strings_checked (
+ mono_get_corlib (), "System", "BadImageFormatException", s, fname, &error);
+ mono_error_assert_ok (&error);
+ return ret;
}
/**
}
}
- free (messages);
+ g_free (messages);
return g_string_free (text, FALSE);
#else
return g_strdup ("");
{
char *trace;
MonoString *res;
- if (!exc)
- mono_raise_exception (mono_get_exception_argument_null ("exception"));
+ if (!exc) {
+ mono_set_pending_exception (mono_get_exception_argument_null ("exception"));
+ return NULL;
+ }
trace = mono_exception_get_native_backtrace (exc);
res = mono_string_new (mono_domain_get (), trace);
}
}
+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 ();
+}