X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fexception.c;h=02b738556c597c72fbc7ed9fe76a5acead5d97eb;hb=0c11be95850671afd7c348493e0b3a6b34eaf524;hp=e2c45aca38bbc615c7547112df6253a7475560bb;hpb=d86a194f618427ab3e91152562d6f4eec7fd89f6;p=mono.git diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index e2c45aca38b..02b738556c5 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -9,9 +9,12 @@ * * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include +#include +#include #include #include @@ -20,12 +23,16 @@ #include #include #include +#include #include #ifdef HAVE_EXECINFO_H #include #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 @@ -172,15 +179,39 @@ mono_exception_from_name_two_strings (MonoImage *image, const char *name_space, 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); } /** @@ -219,16 +250,31 @@ mono_exception_from_token_two_strings (MonoImage *image, guint32 token, 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); } /** @@ -399,8 +445,11 @@ mono_get_exception_type_load (MonoString *class_name, char *assembly_name) { 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; } /** @@ -440,8 +489,11 @@ mono_get_exception_missing_method (const char *class_name, const char *member_na 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; } /** @@ -457,8 +509,11 @@ mono_get_exception_missing_field (const char *class_name, const char *member_nam 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; } /** @@ -562,8 +617,11 @@ mono_get_exception_io (const char *msg) 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; } /** @@ -578,8 +636,11 @@ mono_get_exception_file_not_found2 (const char *msg, MonoString *fname) { 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; } /** @@ -698,8 +759,11 @@ mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname) { 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; } /** @@ -927,7 +991,7 @@ mono_exception_get_native_backtrace (MonoException *exc) } } - free (messages); + g_free (messages); return g_string_free (text, FALSE); #else return g_strdup (""); @@ -939,8 +1003,10 @@ ves_icall_Mono_Runtime_GetNativeStackTrace (MonoException *exc) { 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); @@ -990,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 (); +}