X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fexception.c;h=beece6709d74432af8e3a942362a6dcc9305986d;hb=HEAD;hp=e2e162f702a1efeb69e0226a5a4ab8eedb4d52d4;hpb=8c32f9c042d4e05acf8d712dcb9f00b8362da55f;p=mono.git diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index e2e162f702a..beece6709d7 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -1,5 +1,6 @@ -/* - * exception.c: Exception handling +/** + * \file + * Exception handling * * Authors: * Paolo Molaro (lupus@ximian.com) @@ -13,6 +14,8 @@ */ #include +#include +#include #include #include @@ -21,22 +24,26 @@ #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 - * @name_space: the namespace for the class - * @name: class name + * \param image the Mono image where to look for the class + * \param name_space the namespace for the class + * \param name class name * * Creates an exception of the given namespace/name class in the * current domain. * - * Returns: the initialized exception instance. + * \returns the initialized exception instance. */ MonoException * mono_exception_from_name (MonoImage *image, const char *name_space, @@ -47,15 +54,15 @@ mono_exception_from_name (MonoImage *image, const char *name_space, /** * mono_exception_from_name_domain: - * @domain: Domain where the return object will be created. - * @image: the Mono image where to look for the class - * @name_space: the namespace for the class - * @name: class name + * \param domain Domain where the return object will be created. + * \param image the Mono image where to look for the class + * \param name_space the namespace for the class + * \param name class name * * Creates an exception object of the given namespace/name class on * the given domain. * - * Returns: the initialized exception instance. + * \returns the initialized exception instance. */ MonoException * mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, @@ -85,12 +92,12 @@ mono_exception_from_name_domain (MonoDomain *domain, MonoImage *image, /** * mono_exception_from_token: - * @image: the Mono image where to look for the class - * @token: The type token of the class + * \param image the Mono image where to look for the class + * \param token The type token of the class * - * Creates an exception of the type given by @token. + * Creates an exception of the type given by \p token. * - * Returns: the initialized exception instance. + * \returns the initialized exception instance. */ MonoException * mono_exception_from_token (MonoImage *image, guint32 token) @@ -157,54 +164,82 @@ create_exception_two_strings (MonoClass *klass, MonoString *a1, MonoString *a2, /** * mono_exception_from_name_two_strings: - * @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 + * \param image the Mono image where to look for the class + * \param name_space the namespace for the class + * \param name class name + * \param a1 first string argument to pass + * \param a2 second string argument to pass * * Creates an exception from a constructor that takes two string * arguments. * - * Returns: the initialized exception instance. + * \returns the initialized exception instance. */ MonoException * 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: + * \param image the Mono image where to look for the class + * \param name_space the namespace for the class + * \param name class name + * \param a1 first string argument to pass + * \param a2 second string argument to pass + * \param 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 \p 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 */ + error_init (error); + klass = mono_class_load_from_name (image, name_space, name); - return ret; + return create_exception_two_strings (klass, a1, a2, error); } /** * mono_exception_from_name_msg: - * @image: the Mono image where to look for the class - * @name_space: the namespace for the class - * @name: class name - * @msg: the message to embed inside the exception + * \param image the Mono image where to look for the class + * \param name_space the namespace for the class + * \param name class name + * \param msg the message to embed inside the exception * * Creates an exception and initializes its message field. * - * Returns: the initialized exception instance. + * \returns the initialized exception instance. */ MonoException * mono_exception_from_name_msg (MonoImage *image, const char *name_space, const char *name, const char *msg) { + MonoError error; MonoException *ex; ex = mono_exception_from_name (image, name_space, name); - if (msg) - MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_object_get_domain ((MonoObject*)ex), msg)); + if (msg) { + MonoString *msg_str = mono_string_new_checked (mono_object_get_domain ((MonoObject*)ex), msg, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (ex, message, msg_str); + } return ex; } @@ -220,22 +255,36 @@ 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 */ + 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); } /** * mono_get_exception_divide_by_zero: - * - * Returns: a new instance of the `System.DivideByZeroException` + * \returns a new instance of the \c System.DivideByZeroException */ MonoException * mono_get_exception_divide_by_zero () @@ -246,8 +295,7 @@ mono_get_exception_divide_by_zero () /** * mono_get_exception_security: - * - * Returns: a new instance of the `System.Security.SecurityException` + * \returns a new instance of the \c System.Security.SecurityException */ MonoException * mono_get_exception_security () @@ -258,8 +306,7 @@ mono_get_exception_security () /** * mono_get_exception_thread_abort: - * - * Returns: a new instance of the `System.Threading.ThreadAbortException` + * \returns a new instance of the \c System.Threading.ThreadAbortException */ MonoException * mono_get_exception_thread_abort () @@ -270,8 +317,7 @@ mono_get_exception_thread_abort () /** * mono_get_exception_thread_interrupted: - * - * Returns: a new instance of the `System.Threading.ThreadInterruptedException` + * \returns a new instance of the \c System.Threading.ThreadInterruptedException */ MonoException * mono_get_exception_thread_interrupted () @@ -282,8 +328,7 @@ mono_get_exception_thread_interrupted () /** * mono_get_exception_arithmetic: - * - * Returns: a new instance of the `System.ArithmeticException` + * \returns a new instance of the \c System.ArithmeticException */ MonoException * mono_get_exception_arithmetic () @@ -294,8 +339,7 @@ mono_get_exception_arithmetic () /** * mono_get_exception_overflow: - * - * Returns: a new instance of the `System.OverflowException` + * \returns a new instance of the \c System.OverflowException */ MonoException * mono_get_exception_overflow () @@ -306,8 +350,7 @@ mono_get_exception_overflow () /** * mono_get_exception_null_reference: - * - * Returns: a new instance of the `System.NullReferenceException` + * \returns a new instance of the \c System.NullReferenceException */ MonoException * mono_get_exception_null_reference () @@ -318,9 +361,8 @@ mono_get_exception_null_reference () /** * mono_get_exception_execution_engine: - * @msg: the message to pass to the user - * - * Returns: a new instance of the `System.ExecutionEngineException` + * \param msg the message to pass to the user + * \returns a new instance of the \c System.ExecutionEngineException */ MonoException * mono_get_exception_execution_engine (const char *msg) @@ -330,9 +372,8 @@ mono_get_exception_execution_engine (const char *msg) /** * mono_get_exception_serialization: - * @msg: the message to pass to the user - * - * Returns: a new instance of the `System.Runtime.Serialization.SerializationException` + * \param msg the message to pass to the user + * \returns a new instance of the \c System.Runtime.Serialization.SerializationException */ MonoException * mono_get_exception_serialization (const char *msg) @@ -342,8 +383,7 @@ mono_get_exception_serialization (const char *msg) /** * mono_get_exception_invalid_cast: - * - * Returns: a new instance of the `System.InvalidCastException` + * \returns a new instance of the \c System.InvalidCastException */ MonoException * mono_get_exception_invalid_cast () @@ -353,9 +393,8 @@ mono_get_exception_invalid_cast () /** * mono_get_exception_invalid_operation: - * @msg: the message to pass to the user - * - * Returns: a new instance of the `System.InvalidOperationException` + * \param msg the message to pass to the user + * \returns a new instance of the \c System.InvalidOperationException */ MonoException * mono_get_exception_invalid_operation (const char *msg) @@ -366,8 +405,7 @@ mono_get_exception_invalid_operation (const char *msg) /** * mono_get_exception_index_out_of_range: - * - * Returns: a new instance of the `System.IndexOutOfRangeException` + * \returns a new instance of the \c System.IndexOutOfRangeException */ MonoException * mono_get_exception_index_out_of_range () @@ -378,8 +416,7 @@ mono_get_exception_index_out_of_range () /** * mono_get_exception_array_type_mismatch: - * - * Returns: a new instance of the `System.ArrayTypeMismatchException` + * \returns a new instance of the \c System.ArrayTypeMismatchException */ MonoException * mono_get_exception_array_type_mismatch () @@ -390,25 +427,31 @@ mono_get_exception_array_type_mismatch () /** * mono_get_exception_type_load: - * @class_name: the name of the class that could not be loaded - * @assembly_name: the assembly where the class was looked up. - * - * Returns: a new instance of the `System.TypeLoadException` + * \param class_name the name of the class that could not be loaded + * \param assembly_name the assembly where the class was looked up. + * \returns a new instance of the \c System.TypeLoadException */ MonoException * 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; + MonoString *s = NULL; + if (assembly_name) { + s = mono_string_new_checked (mono_domain_get (), assembly_name, &error); + mono_error_assert_ok (&error); + } else + s = mono_string_empty (mono_domain_get ()); + + 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; } /** * mono_get_exception_not_implemented: - * @msg: the message to pass to the user - * - * Returns: a new instance of the `System.NotImplementedException` + * \param msg the message to pass to the user + * \returns a new instance of the \c System.NotImplementedException */ MonoException * mono_get_exception_not_implemented (const char *msg) @@ -418,9 +461,8 @@ mono_get_exception_not_implemented (const char *msg) /** * mono_get_exception_not_supported: - * @msg: the message to pass to the user - * - * Returns: a new instance of the `System.NotSupportedException` + * \param msg the message to pass to the user + * \returns a new instance of the \c System.NotSupportedException */ MonoException * mono_get_exception_not_supported (const char *msg) @@ -430,43 +472,50 @@ mono_get_exception_not_supported (const char *msg) /** * mono_get_exception_missing_method: - * @class_name: the class where the lookup was performed. - * @member_name: the name of the missing method. - * - * Returns: a new instance of the `System.MissingMethodException` + * \param class_name the class where the lookup was performed. + * \param member_name the name of the missing method. + * \returns a new instance of the \c System.MissingMethodException */ MonoException * mono_get_exception_missing_method (const char *class_name, const char *member_name) { - MonoString *s1 = mono_string_new (mono_domain_get (), class_name); - MonoString *s2 = mono_string_new (mono_domain_get (), member_name); + MonoError error; + MonoString *s1 = mono_string_new_checked (mono_domain_get (), class_name, &error); + mono_error_assert_ok (&error); + MonoString *s2 = mono_string_new_checked (mono_domain_get (), member_name, &error); + mono_error_assert_ok (&error); - return mono_exception_from_name_two_strings (mono_get_corlib (), "System", - "MissingMethodException", s1, s2); + MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", + "MissingMethodException", s1, s2, &error); + mono_error_assert_ok (&error); + return ret; } /** * mono_get_exception_missing_field: - * @class_name: the class where the lookup was performed - * @member_name: the name of the missing method. - * - * Returns: a new instance of the `System.MissingFieldException` + * \param class_name the class where the lookup was performed + * \param member_name the name of the missing method. + * \returns a new instance of the \c System.MissingFieldException */ MonoException * mono_get_exception_missing_field (const char *class_name, const char *member_name) { - MonoString *s1 = mono_string_new (mono_domain_get (), class_name); - MonoString *s2 = mono_string_new (mono_domain_get (), member_name); + MonoError error; + MonoString *s1 = mono_string_new_checked (mono_domain_get (), class_name, &error); + mono_error_assert_ok (&error); + MonoString *s2 = mono_string_new_checked (mono_domain_get (), member_name, &error); + mono_error_assert_ok (&error); - return mono_exception_from_name_two_strings (mono_get_corlib (), "System", - "MissingFieldException", s1, s2); + MonoException *ret = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", + "MissingFieldException", s1, s2, &error); + mono_error_assert_ok (&error); + return ret; } /** * mono_get_exception_argument_null: - * @arg: the name of the argument that is null - * - * Returns: a new instance of the `System.ArgumentNullException` + * \param arg the name of the argument that is null + * \returns a new instance of the \c System.ArgumentNullException */ MonoException* mono_get_exception_argument_null (const char *arg) @@ -477,8 +526,11 @@ mono_get_exception_argument_null (const char *arg) mono_get_corlib (), "System", "ArgumentNullException"); if (arg) { + MonoError error; MonoArgumentException *argex = (MonoArgumentException *)ex; - MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg)); + MonoString *arg_str = mono_string_new_checked (mono_object_get_domain ((MonoObject*)ex), arg, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (argex, param_name, arg_str); } return ex; @@ -486,9 +538,8 @@ mono_get_exception_argument_null (const char *arg) /** * mono_get_exception_argument: - * @arg: the name of the invalid argument. - * - * Returns: a new instance of the `System.ArgumentException` + * \param arg the name of the invalid argument. + * \returns a new instance of the \c System.ArgumentException */ MonoException * mono_get_exception_argument (const char *arg, const char *msg) @@ -499,8 +550,11 @@ mono_get_exception_argument (const char *arg, const char *msg) mono_get_corlib (), "System", "ArgumentException", msg); if (arg) { + MonoError error; MonoArgumentException *argex = (MonoArgumentException *)ex; - MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg)); + MonoString *arg_str = mono_string_new_checked (mono_object_get_domain ((MonoObject*)ex), arg, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (argex, param_name, arg_str); } return ex; @@ -508,9 +562,8 @@ mono_get_exception_argument (const char *arg, const char *msg) /** * mono_get_exception_argument_out_of_range: - * @arg: the name of the out of range argument. - * - * Returns: a new instance of the `System.ArgumentOutOfRangeException` + * \param arg the name of the out of range argument. + * \returns a new instance of the \c System.ArgumentOutOfRangeException */ MonoException * mono_get_exception_argument_out_of_range (const char *arg) @@ -521,8 +574,11 @@ mono_get_exception_argument_out_of_range (const char *arg) mono_get_corlib (), "System", "ArgumentOutOfRangeException"); if (arg) { + MonoError error; MonoArgumentException *argex = (MonoArgumentException *)ex; - MONO_OBJECT_SETREF (argex, param_name, mono_string_new (mono_object_get_domain ((MonoObject*)ex), arg)); + MonoString *arg_str = mono_string_new_checked (mono_object_get_domain ((MonoObject*)ex), arg, &error); + mono_error_assert_ok (&error); + MONO_OBJECT_SETREF (argex, param_name, arg_str); } return ex; @@ -530,9 +586,8 @@ mono_get_exception_argument_out_of_range (const char *arg) /** * mono_get_exception_thread_state: - * @msg: the message to present to the user - * - * Returns: a new instance of the `System.Threading.ThreadStateException` + * \param msg the message to present to the user + * \returns a new instance of the \c System.Threading.ThreadStateException */ MonoException * mono_get_exception_thread_state (const char *msg) @@ -543,9 +598,8 @@ mono_get_exception_thread_state (const char *msg) /** * mono_get_exception_io: - * @msg: the message to present to the user - * - * Returns: a new instance of the `System.IO.IOException` + * \param msg the message to present to the user + * \returns a new instance of the \c System.IO.IOException */ MonoException * mono_get_exception_io (const char *msg) @@ -556,39 +610,46 @@ mono_get_exception_io (const char *msg) /** * mono_get_exception_file_not_found: - * @fname: the name of the file not found. - * - * Returns: a new instance of the `System.IO.FileNotFoundException` + * \param fname the name of the file not found. + * \returns a new instance of the \c System.IO.FileNotFoundException */ 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; } /** * mono_get_exception_file_not_found2: - * @msg: an informative message for the user. - * @fname: the name of the file not found. - * - * Returns: a new instance of the `System.IO.FileNotFoundException` + * \param msg an informative message for the user. + * \param fname the name of the file not found. + * \returns a new instance of the \c System.IO.FileNotFoundException */ MonoException * mono_get_exception_file_not_found2 (const char *msg, MonoString *fname) { - MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL; + MonoError error; + MonoString *s = NULL; + if (msg) { + s = mono_string_new_checked (mono_domain_get (), msg, &error); + mono_error_assert_ok (&error); + } - return mono_exception_from_name_two_strings ( - mono_get_corlib (), "System.IO", "FileNotFoundException", s, fname); + 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; } /** * mono_get_exception_type_initialization: - * @type_name: the name of the type that failed to initialize. - * @inner: the inner exception. - * - * Returns: a new instance of the `System.TypeInitializationException` + * \param type_name the name of the type that failed to initialize. + * \param inner the inner exception. + * \returns a new instance of the \c System.TypeInitializationException */ MonoException * mono_get_exception_type_initialization (const gchar *type_name, MonoException *inner) @@ -612,6 +673,8 @@ mono_get_exception_type_initialization_checked (const gchar *type_name, MonoExce MonoMethod *method; gpointer iter; + error_init (error); + klass = mono_class_load_from_name (mono_get_corlib (), "System", "TypeInitializationException"); mono_class_init (klass); @@ -628,7 +691,9 @@ mono_get_exception_type_initialization_checked (const gchar *type_name, MonoExce } g_assert (method); - args [0] = mono_string_new (mono_domain_get (), type_name); + MonoString *type_name_str = mono_string_new_checked (mono_domain_get (), type_name, error); + mono_error_assert_ok (error); + args [0] = type_name_str; args [1] = inner; exc = mono_object_new_checked (mono_domain_get (), klass, error); @@ -642,9 +707,8 @@ mono_get_exception_type_initialization_checked (const gchar *type_name, MonoExce /** * mono_get_exception_synchronization_lock: - * @inner: the inner exception. - * - * Returns: a new instance of the `System.SynchronizationLockException` + * \param inner the inner exception. + * \returns a new instance of the \c System.SynchronizationLockException */ MonoException * mono_get_exception_synchronization_lock (const char *msg) @@ -654,9 +718,8 @@ mono_get_exception_synchronization_lock (const char *msg) /** * mono_get_exception_cannot_unload_appdomain: - * @inner: the inner exception. - * - * Returns: a new instance of the `System.CannotUnloadAppDomainException` + * \param inner the inner exception. + * \returns a new instance of the \c System.CannotUnloadAppDomainException */ MonoException * mono_get_exception_cannot_unload_appdomain (const char *msg) @@ -666,8 +729,7 @@ mono_get_exception_cannot_unload_appdomain (const char *msg) /** * mono_get_exception_appdomain_unloaded - * - * Returns: a new instance of the `System.AppDomainUnloadedException` + * \returns a new instance of the \c System.AppDomainUnloadedException */ MonoException * mono_get_exception_appdomain_unloaded (void) @@ -677,9 +739,8 @@ mono_get_exception_appdomain_unloaded (void) /** * mono_get_exception_bad_image_format: - * @msg: an informative message for the user. - * - * Returns: a new instance of the `System.BadImageFormatException` + * \param msg an informative message for the user. + * \returns a new instance of the \c System.BadImageFormatException */ MonoException * mono_get_exception_bad_image_format (const char *msg) @@ -689,24 +750,30 @@ mono_get_exception_bad_image_format (const char *msg) /** * mono_get_exception_bad_image_format2: - * @msg: an informative message for the user. - * @fname: The full name of the file with the invalid image. - * - * Returns: a new instance of the `System.BadImageFormatException` + * \param msg an informative message for the user. + * \param fname The full name of the file with the invalid image. + * \returns a new instance of the \c System.BadImageFormatException */ MonoException * mono_get_exception_bad_image_format2 (const char *msg, MonoString *fname) { - MonoString *s = msg ? mono_string_new (mono_domain_get (), msg) : NULL; + MonoError error; + MonoString *s = NULL; - return mono_exception_from_name_two_strings ( - mono_get_corlib (), "System", "BadImageFormatException", s, fname); + if (msg) { + s = mono_string_new_checked (mono_domain_get (), msg, &error); + mono_error_assert_ok (&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; } /** * mono_get_exception_stack_overflow: - * - * Returns: a new instance of the `System.StackOverflowException` + * \returns a new instance of the \c System.StackOverflowException */ MonoException * mono_get_exception_stack_overflow (void) @@ -716,8 +783,7 @@ mono_get_exception_stack_overflow (void) /** * mono_get_exception_out_of_memory: - * - * Returns: a new instance of the `System.OutOfMemoryException` + * \returns a new instance of the \c System.OutOfMemoryException */ MonoException * mono_get_exception_out_of_memory (void) @@ -727,8 +793,7 @@ mono_get_exception_out_of_memory (void) /** * mono_get_exception_field_access: - * - * Returns: a new instance of the `System.FieldAccessException` + * \returns a new instance of the \c System.FieldAccessException */ MonoException * mono_get_exception_field_access (void) @@ -738,9 +803,8 @@ mono_get_exception_field_access (void) /** * mono_get_exception_field_access2: - * @msg: an informative message for the user. - * - * Returns: a new instance of the `System.FieldAccessException` + * \param msg an informative message for the user. + * \returns a new instance of the \c System.FieldAccessException */ MonoException * mono_get_exception_field_access_msg (const char *msg) @@ -750,8 +814,7 @@ mono_get_exception_field_access_msg (const char *msg) /** * mono_get_exception_method_access: - * - * Returns: a new instance of the `System.MethodAccessException` + * \returns a new instance of the \c System.MethodAccessException */ MonoException * mono_get_exception_method_access (void) @@ -761,9 +824,8 @@ mono_get_exception_method_access (void) /** * mono_get_exception_method_access2: - * @msg: an informative message for the user. - * - * Returns: a new instance of the `System.MethodAccessException` + * \param msg an informative message for the user. + * \returns a new instance of the \c System.MethodAccessException */ MonoException * mono_get_exception_method_access_msg (const char *msg) @@ -773,33 +835,38 @@ mono_get_exception_method_access_msg (const char *msg) /** * mono_get_exception_reflection_type_load: - * @types: an array of types that were defined in the moduled loaded. - * @exceptions: an array of exceptions that were thrown during the type loading. - * - * Returns: a new instance of the `System.Reflection.ReflectionTypeLoadException` + * \param types an array of types that were defined in the moduled loaded. + * \param exceptions an array of exceptions that were thrown during the type loading. + * \returns a new instance of the \c System.Reflection.ReflectionTypeLoadException */ MonoException * -mono_get_exception_reflection_type_load (MonoArray *types, MonoArray *exceptions) +mono_get_exception_reflection_type_load (MonoArray *types_raw, MonoArray *exceptions_raw) { + HANDLE_FUNCTION_ENTER (); MonoError error; - MonoException *ret = mono_get_exception_reflection_type_load_checked (types, exceptions, &error); + MONO_HANDLE_DCL (MonoArray, types); + MONO_HANDLE_DCL (MonoArray, exceptions); + MonoExceptionHandle ret = mono_get_exception_reflection_type_load_checked (types, exceptions, &error); if (is_ok (&error)) { mono_error_cleanup (&error); - return NULL; + ret = MONO_HANDLE_CAST (MonoException, NULL_HANDLE); + goto leave; } - return ret; +leave: + HANDLE_FUNCTION_RETURN_OBJ (ret); + } -MonoException * -mono_get_exception_reflection_type_load_checked (MonoArray *types, MonoArray *exceptions, MonoError *error) +MonoExceptionHandle +mono_get_exception_reflection_type_load_checked (MonoArrayHandle types, MonoArrayHandle exceptions, MonoError *error) { MonoClass *klass; - gpointer args [2]; - MonoObject *exc; MonoMethod *method; gpointer iter; + error_init (error); + klass = mono_class_load_from_name (mono_get_corlib (), "System.Reflection", "ReflectionTypeLoadException"); mono_class_init (klass); @@ -817,18 +884,22 @@ mono_get_exception_reflection_type_load_checked (MonoArray *types, MonoArray *ex } g_assert (method); - args [0] = types; - args [1] = exceptions; - - exc = mono_object_new_checked (mono_domain_get (), klass, error); + MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_object_new_checked (mono_domain_get (), klass, error)); mono_error_assert_ok (error); - mono_runtime_invoke_checked (method, exc, args, error); - return_val_if_nok (error, NULL); + gpointer args [2]; + args [0] = MONO_HANDLE_RAW (types); + args [1] = MONO_HANDLE_RAW (exceptions); - return (MonoException *) exc; + mono_runtime_invoke_checked (method, MONO_HANDLE_RAW (exc), args, error); + return_val_if_nok (error, MONO_HANDLE_CAST (MonoException, NULL_HANDLE)); + + return exc; } +/** + * mono_get_exception_runtime_wrapped: + */ MonoException * mono_get_exception_runtime_wrapped (MonoObject *wrapped_exception) { @@ -899,25 +970,32 @@ mono_exception_get_managed_backtrace (MonoException *exc) } char * -mono_exception_get_native_backtrace (MonoException *exc) +mono_exception_handle_get_native_backtrace (MonoExceptionHandle exc) { #ifdef HAVE_BACKTRACE_SYMBOLS MonoDomain *domain; - MonoArray *arr = exc->native_trace_ips; + MonoArrayHandle arr = MONO_HANDLE_NEW(MonoArray, NULL); int i, len; GString *text; char **messages; - if (!arr) + MONO_HANDLE_GET (arr, exc, native_trace_ips); + + if (MONO_HANDLE_IS_NULL(arr)) return g_strdup (""); domain = mono_domain_get (); - len = mono_array_length (arr); + len = mono_array_handle_length (arr); text = g_string_new_len (NULL, len * 20); - messages = backtrace_symbols (mono_array_addr (arr, gpointer, 0), len); - + uint32_t gchandle; + void *addr = MONO_ARRAY_HANDLE_PIN (arr, gpointer, 0, &gchandle); + MONO_ENTER_GC_SAFE; + messages = backtrace_symbols (addr, len); + MONO_EXIT_GC_SAFE; + mono_gchandle_free (gchandle); for (i = 0; i < len; ++i) { - gpointer ip = mono_array_get (arr, gpointer, i); + gpointer ip; + MONO_HANDLE_ARRAY_GETVAL (ip, arr, gpointer, i); MonoJitInfo *ji = mono_jit_info_table_find (mono_domain_get (), (char *)ip); if (ji) { char *msg = mono_debug_print_stack_frame (mono_jit_info_get_method (ji), (char*)ip - (char*)ji->code_start, domain); @@ -928,38 +1006,40 @@ mono_exception_get_native_backtrace (MonoException *exc) } } - free (messages); + g_free (messages); return g_string_free (text, FALSE); #else return g_strdup (""); #endif } -MonoString * -ves_icall_Mono_Runtime_GetNativeStackTrace (MonoException *exc) +MonoStringHandle +ves_icall_Mono_Runtime_GetNativeStackTrace (MonoExceptionHandle exc, MonoError *error) { char *trace; - MonoString *res; + MonoStringHandle res; + error_init (error); + if (!exc) { - mono_set_pending_exception (mono_get_exception_argument_null ("exception")); - return NULL; + mono_error_set_argument_null (error, "exception", ""); + return NULL_HANDLE_STRING; } - trace = mono_exception_get_native_backtrace (exc); - res = mono_string_new (mono_domain_get (), trace); + trace = mono_exception_handle_get_native_backtrace (exc); + res = mono_string_new_handle (mono_domain_get (), trace, error); g_free (trace); return res; } /** * mono_error_raise_exception: - * @target_error: the exception to raise + * \param target_error the exception to raise * - * Raises the exception of @target_error. - * Does nothing if @target_error has a success error code. + * Raises the exception of \p target_error. + * Does nothing if \p target_error has a success error code. * Aborts in case of a double fault. This happens when it can't recover from an error caused by trying * to construct the first exception object. - * The error object @target_error is cleaned up. + * The error object \p target_error is cleaned up. */ void mono_error_raise_exception (MonoError *target_error) @@ -971,11 +1051,9 @@ mono_error_raise_exception (MonoError *target_error) /** * mono_error_set_pending_exception: - * @error: The error - * - * - * If @error is set, convert it to an exception and set the pending exception for the current icall. - * Returns TRUE if @error was set, or FALSE otherwise, so that you can write: + * \param error The error + * If \p error is set, convert it to an exception and set the pending exception for the current icall. + * \returns TRUE if \p error was set, or FALSE otherwise, so that you can write: * if (mono_error_set_pending_exception (error)) { * { ... cleanup code ... } * return; @@ -993,3 +1071,50 @@ mono_error_set_pending_exception (MonoError *error) } } +void +mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, void *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 (); +}