Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormonojenkins <jo.shields+jenkins@xamarin.com>2016-01-26 22:15:17 +0300
committermonojenkins <jo.shields+jenkins@xamarin.com>2016-01-26 22:15:17 +0300
commit0658b3879aaa68b0b1124a56da4845c131fe10b4 (patch)
tree16f1aafc5445f4f41e65bb7652c2e85687af4418
parent1a2b21803c38f3aeabb6cceef2a0be0309123b66 (diff)
parent305bfbae4ce3b4b616879578f390f9f540dbe38f (diff)
Merge pull request #2516 from lambdageek/monoerror-exception_instance
[runtime] Add MONO_ERROR_EXCEPTION_INSTANCE MonoError This kind of MonoError can encapsulate a managed MonoException object. (For example as a result of mono_runtime_invoke ()). Issues: - [x] Memory leak correctness. `MonoError` already leaks memory if you simply swallow it without calling `mono_error_cleanup` or some function that calls it (for example `mono_error_raise_exception` or `mono_error_convert_to_exception`). Now if we have an encapsulated exception, we'll leak a GC handle unless cleanup happens.
-rw-r--r--mono/utils/mono-error-internals.h14
-rw-r--r--mono/utils/mono-error.c76
-rw-r--r--mono/utils/mono-error.h4
3 files changed, 76 insertions, 18 deletions
diff --git a/mono/utils/mono-error-internals.h b/mono/utils/mono-error-internals.h
index 774203d343c..926e76c9bbd 100644
--- a/mono/utils/mono-error-internals.h
+++ b/mono/utils/mono-error-internals.h
@@ -15,7 +15,16 @@ typedef struct {
const char *member_name;
const char *exception_name_space;
const char *exception_name;
- MonoClass *klass;
+ union {
+ /* Valid if error_code != MONO_ERROR_EXCEPTION_INSTANCE.
+ * Used by type or field load errors and generic error specified by class.
+ */
+ MonoClass *klass;
+ /* Valid if error_code == MONO_ERROR_EXCEPTION_INSTANCE.
+ * Generic error specified by a managed instance.
+ */
+ uint32_t instance_handle;
+ } exn;
const char *full_message;
const char *full_message_with_fields;
const char *first_argument;
@@ -77,6 +86,9 @@ void
mono_error_set_generic_error (MonoError *error, const char * name_space, const char *name, const char *msg_format, ...);
void
+mono_error_set_exception_instance (MonoError *error, MonoException *exc);
+
+void
mono_error_set_from_loader_error (MonoError *error);
MonoException*
diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c
index 4ac7d6766ef..ca3350c5fd4 100644
--- a/mono/utils/mono-error.c
+++ b/mono/utils/mono-error.c
@@ -13,6 +13,8 @@
#include <mono/metadata/exception.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/object-internals.h>
#define set_error_message() do { \
va_list args; \
@@ -22,6 +24,12 @@
va_end (args); \
} while (0)
+static gboolean
+is_managed_exception (MonoErrorInternal *error)
+{
+ return (error->error_code == MONO_ERROR_EXCEPTION_INSTANCE);
+}
+
static void
mono_error_prepare (MonoErrorInternal *error)
{
@@ -29,7 +37,18 @@ mono_error_prepare (MonoErrorInternal *error)
return;
error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = error->first_argument = NULL;
- error->klass = NULL;
+ error->exn.klass = NULL;
+}
+
+static MonoClass*
+get_class (MonoErrorInternal *error)
+{
+ MonoClass *klass = NULL;
+ if (is_managed_exception (error))
+ klass = mono_object_class (mono_gchandle_get_target (error->exn.instance_handle));
+ else
+ klass = error->exn.klass;
+ return klass;
}
static const char*
@@ -37,8 +56,9 @@ get_type_name (MonoErrorInternal *error)
{
if (error->type_name)
return error->type_name;
- if (error->klass)
- return error->klass->name;
+ MonoClass *klass = get_class (error);
+ if (klass)
+ return klass->name;
return "<unknown type>";
}
@@ -47,8 +67,9 @@ get_assembly_name (MonoErrorInternal *error)
{
if (error->assembly_name)
return error->assembly_name;
- if (error->klass && error->klass->image)
- return error->klass->image->name;
+ MonoClass *klass = get_class (error);
+ if (klass && klass->image)
+ return klass->image->name;
return "<unknown assembly>";
}
@@ -75,6 +96,9 @@ mono_error_cleanup (MonoError *oerror)
if (error->error_code == MONO_ERROR_NONE)
return;
+ if (is_managed_exception (error))
+ mono_gchandle_free (error->exn.instance_handle);
+
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
@@ -196,7 +220,9 @@ mono_error_set_class (MonoError *oerror, MonoClass *klass)
{
MonoErrorInternal *error = (MonoErrorInternal*)oerror;
- error->klass = klass;
+ if (is_managed_exception (error))
+ return;
+ error->exn.klass = klass;
}
static void
@@ -317,6 +343,15 @@ mono_error_set_generic_error (MonoError *oerror, const char * name_space, const
}
void
+mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
+{
+ MonoErrorInternal *error = (MonoErrorInternal*)oerror;
+
+ error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
+ error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
+}
+
+void
mono_error_set_from_loader_error (MonoError *oerror)
{
MonoLoaderError *loader_error = mono_loader_get_last_error ();
@@ -403,7 +438,7 @@ mono_loader_set_error_from_mono_error (MonoError *oerror)
mono_loader_set_error_method_load (get_type_name (error), error->member_name);
break;
case MONO_ERROR_MISSING_FIELD:
- mono_loader_set_error_field_load (error->klass, error->member_name);
+ mono_loader_set_error_field_load (error->exn.klass, error->member_name);
break;
case MONO_ERROR_TYPE_LOAD:
mono_loader_set_error_type_load (get_type_name (error), get_assembly_name (error));
@@ -415,6 +450,8 @@ mono_loader_set_error_from_mono_error (MonoError *oerror)
case MONO_ERROR_BAD_IMAGE:
mono_loader_set_error_bad_image (g_strdup (error->full_message));
break;
+ case MONO_ERROR_EXCEPTION_INSTANCE:
+ mono_loader_set_error_bad_image (g_strdup_printf ("Non translatable error"));
default:
mono_loader_set_error_bad_image (g_strdup_printf ("Non translatable error: %s", error->full_message));
}
@@ -467,11 +504,14 @@ get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, Mono
if (error->type_name) {
res = mono_string_new (domain, error->type_name);
- } else if (error->klass) {
- char *name = mono_type_full_name (&error->klass->byval_arg);
- if (name) {
- res = mono_string_new (domain, name);
- g_free (name);
+ } else {
+ MonoClass *klass = get_class (error);
+ if (klass) {
+ char *name = mono_type_full_name (&klass->byval_arg);
+ if (name) {
+ res = mono_string_new (domain, name);
+ g_free (name);
+ }
}
}
if (!res)
@@ -506,7 +546,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
return NULL;
case MONO_ERROR_MISSING_METHOD:
- if ((error->type_name || error->klass) && error->member_name) {
+ if ((error->type_name || error->exn.klass) && error->member_name) {
type_name = get_type_name_as_mono_string (error, domain, error_out);
if (!mono_error_ok (error_out))
break;
@@ -526,7 +566,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
break;
case MONO_ERROR_MISSING_FIELD:
- if ((error->type_name || error->klass) && error->member_name) {
+ if ((error->type_name || error->exn.klass) && error->member_name) {
type_name = get_type_name_as_mono_string (error, domain, error_out);
if (!mono_error_ok (error_out))
break;
@@ -606,8 +646,8 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
case MONO_ERROR_NOT_VERIFIABLE: {
char *type_name = NULL, *message;
- if (error->klass) {
- type_name = mono_type_get_full_name (error->klass);
+ if (error->exn.klass) {
+ type_name = mono_type_get_full_name (error->exn.klass);
if (!type_name) {
mono_error_set_out_of_memory (error_out, "Could not allocate message");
break;
@@ -631,6 +671,10 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
break;
+ case MONO_ERROR_EXCEPTION_INSTANCE:
+ exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
+ break;
+
default:
mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
}
diff --git a/mono/utils/mono-error.h b/mono/utils/mono-error.h
index 12747711fc4..58a401c13ec 100644
--- a/mono/utils/mono-error.h
+++ b/mono/utils/mono-error.h
@@ -29,7 +29,9 @@ enum {
* This is a generic error mechanism is you need to raise an arbitrary corlib exception.
* You must pass the exception name otherwise prepare_exception will fail with internal execution.
*/
- MONO_ERROR_GENERIC = 9
+ MONO_ERROR_GENERIC = 9,
+ /* This one encapsulates a managed exception instance */
+ MONO_ERROR_EXCEPTION_INSTANCE = 10
};
/*Keep in sync with MonoErrorInternal*/