[threads] Add function to stringify thread state names.
[mono.git] / mono / utils / mono-error.c
index 25bc906ba51f94bb6e585b19fa55a429996ea07b..841a354afaff6f61ea232b97a6a82be54d4af8d8 100644 (file)
@@ -11,7 +11,6 @@
 #include "mono-error-internals.h"
 
 #include <mono/metadata/exception.h>
-#include <mono/metadata/object-internals.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/debug-helpers.h>
 
@@ -35,11 +34,31 @@ mono_error_prepare (MonoErrorInternal *error)
        if (error->error_code != MONO_ERROR_NONE)
                return;
 
-       error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = NULL;
+       error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = NULL;
        error->klass = NULL;
        error->message [0] = 0;
 }
 
+static const char*
+get_type_name (MonoErrorInternal *error)
+{
+       if (error->type_name)
+               return error->type_name;
+       if (error->klass)
+               return error->klass->name;
+       return "<unknown type>";
+}
+
+static const char*
+get_assembly_name (MonoErrorInternal *error)
+{
+       if (error->assembly_name)
+               return error->assembly_name;
+       if (error->klass && error->klass->image)
+               return error->klass->image->name;
+       return "<unknown assembly>";
+}
+
 void
 mono_error_init_flags (MonoError *oerror, unsigned short flags)
 {
@@ -64,6 +83,7 @@ mono_error_cleanup (MonoError *oerror)
                return;
 
        g_free ((char*)error->full_message);
+       g_free ((char*)error->full_message_with_fields);
        if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
                return;
 
@@ -80,6 +100,15 @@ mono_error_ok (MonoError *error)
        return error->error_code == MONO_ERROR_NONE;
 }
 
+void
+mono_error_assert_ok (MonoError *error)
+{
+       if (mono_error_ok (error))
+               return;
+
+       g_error ("%s\n", mono_error_get_message (error));
+}
+
 unsigned short
 mono_error_get_error_code (MonoError *error)
 {
@@ -94,7 +123,16 @@ mono_error_get_message (MonoError *oerror)
        MonoErrorInternal *error = (MonoErrorInternal*)oerror;
        if (error->error_code == MONO_ERROR_NONE)
                return NULL;
-       return mono_internal_error_get_message (error);
+       if (error->full_message_with_fields)
+               return error->full_message_with_fields;
+
+       error->full_message_with_fields = g_strdup_printf ("%s assembly:%s type:%s member:%s",
+               mono_internal_error_get_message (error),
+               get_assembly_name (error),
+               get_type_name (error),
+               error->member_name ? error->member_name : "<none>");
+
+       return error->full_message_with_fields ? error->full_message_with_fields : mono_internal_error_get_message (error);
 }
 
 /*
@@ -188,6 +226,16 @@ mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, cons
        set_error_message ();
 }
 
+
+void
+mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only)
+{
+       if (refection_only)
+               mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
+       else
+               mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies.");
+}
+
 void
 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
 {
@@ -199,6 +247,10 @@ mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char
        set_error_message ();
 }
 
+/*
+ * Different than other functions, this one here assumes that type_name and assembly_name to have been allocated just for us.
+ * Which means mono_error_cleanup will free them.
+ */
 void
 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
 {
@@ -208,6 +260,7 @@ mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const c
        error->error_code = MONO_ERROR_TYPE_LOAD;
        mono_error_set_type_name (oerror, type_name);
        mono_error_set_assembly_name (oerror, assembly_name);
+       mono_error_dup_strings (oerror, FALSE);
        set_error_message ();
 }
 
@@ -273,10 +326,10 @@ mono_error_set_from_loader_error (MonoError *oerror)
 {
        MonoLoaderError *loader_error = mono_loader_get_last_error ();
        MonoErrorInternal *error = (MonoErrorInternal*)oerror;
+       gboolean dup_strings = TRUE;
 
        mono_error_prepare (error);
 
-
        if (!loader_error) {
                mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from an empty loader-error");
                return;
@@ -286,10 +339,6 @@ mono_error_set_from_loader_error (MonoError *oerror)
        case MONO_EXCEPTION_NONE:
                mono_error_set_generic_error (oerror, "System", "ExecutionEngineException", "Runtime tried to produce a mono-error from a non-error loader-error");
                break;
-       case MONO_EXCEPTION_SECURITY_LINKDEMAND:
-       case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND:
-               mono_error_set_generic_error (oerror, "System.Security", "SecurityException", "Failed for unknown reasons.");
-               break;
 
        case MONO_EXCEPTION_INVALID_PROGRAM:
                mono_error_set_generic_error (oerror, "System", "InvalidProgramException", "Failed for unknown reasons.");
@@ -311,14 +360,12 @@ mono_error_set_from_loader_error (MonoError *oerror)
                break;
 
        case MONO_EXCEPTION_TYPE_LOAD:
-               mono_error_set_type_load_name (oerror, loader_error->class_name, loader_error->assembly_name, "Failed for unknown reasons.");
+               mono_error_set_type_load_name (oerror, g_strdup (loader_error->class_name), g_strdup (loader_error->assembly_name), "Failed for unknown reasons.");
+               dup_strings = FALSE;
                break;
        
        case MONO_EXCEPTION_FILE_NOT_FOUND:
-               if (loader_error->ref_only)
-                       mono_error_set_assembly_load (oerror, loader_error->assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
-               else
-                       mono_error_set_assembly_load (oerror, loader_error->assembly_name, "Could not load file or assembly or one of its dependencies.");
+               mono_error_set_assembly_load_simple (oerror, loader_error->assembly_name, loader_error->ref_only);
                break;
 
        case MONO_EXCEPTION_METHOD_ACCESS:
@@ -347,30 +394,10 @@ mono_error_set_from_loader_error (MonoError *oerror)
                break;
        }
 
-       mono_error_dup_strings (oerror, TRUE);
+       mono_error_dup_strings (oerror, dup_strings);
        mono_loader_clear_error ();
 }
 
-static const char*
-get_type_name (MonoErrorInternal *error)
-{
-       if (error->type_name)
-               return error->type_name;
-       if (error->klass)
-               return error->klass->name;
-       return "<unknown type>";
-}
-
-static const char*
-get_assembly_name (MonoErrorInternal *error)
-{
-       if (error->assembly_name)
-               return error->assembly_name;
-       if (error->klass && error->klass->image)
-               return error->klass->image->name;
-       return "<unknown assembly>";
-}
-
 void
 mono_loader_set_error_from_mono_error (MonoError *oerror)
 {
@@ -430,9 +457,10 @@ mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char
        mono_error_prepare (error);
 
        error->error_code = MONO_ERROR_NOT_VERIFIABLE;
-       mono_error_set_class (oerror, method->klass);
-       if (method)
+       if (method) {
+               mono_error_set_class (oerror, method->klass);
                mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
+       }
 
        set_error_message ();
 }
@@ -622,20 +650,18 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
 }
 
 /*
-Raises the exception of @error.
-Does nothing if @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 @error is cleaned up. 
+Convert this MonoError to an exception if it's faulty or return NULL.
+The error object is cleant after.
 */
-void
-mono_error_raise_exception (MonoError *target_error)
+
+MonoException*
+mono_error_convert_to_exception (MonoError *target_error)
 {
        MonoError error;
        MonoException *ex;
 
        if (mono_error_ok (target_error))
-               return;
+               return NULL;
 
        ex = mono_error_prepare_exception (target_error, &error);
        if (!mono_error_ok (&error)) {
@@ -647,6 +673,5 @@ mono_error_raise_exception (MonoError *target_error)
                mono_error_cleanup (&error);
        }
        mono_error_cleanup (target_error);
-
-       mono_raise_exception (ex);      
+       return ex;
 }