X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-error.c;h=55f84ffd8e8f1de87aab2c64464ebab9d3955ea6;hb=8e6f129087207e14b5bc411554229441a7b522e6;hp=7e186b6b717ce06b2f4103bb2ab3abe22e5ce2df;hpb=4cf9ffd6cfffb63891502f232ce6a52a837203ea;p=mono.git diff --git a/mono/utils/mono-error.c b/mono/utils/mono-error.c index 7e186b6b717..55f84ffd8e8 100644 --- a/mono/utils/mono-error.c +++ b/mono/utils/mono-error.c @@ -38,6 +38,12 @@ is_managed_exception (MonoErrorInternal *error) return (error->error_code == MONO_ERROR_EXCEPTION_INSTANCE); } +static gboolean +is_boxed (MonoErrorInternal *error) +{ + return ((error->flags & MONO_ERROR_MEMPOOL_BOXED) != 0); +} + static void mono_error_prepare (MonoErrorInternal *error) { @@ -116,6 +122,8 @@ mono_error_cleanup (MonoError *oerror) /* Two cleanups in a row without an intervening init. */ g_assert (orig_error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL); + /* Mempool stored error shouldn't be cleaned up */ + g_assert (!is_boxed (error)); /* Mark it as cleaned up. */ error->error_code = MONO_ERROR_CLEANUP_CALLED_SENTINEL; @@ -289,18 +297,27 @@ mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_nam 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."); + mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly '%s' or one of its dependencies.", assembly_name); } void mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...) +{ + va_list args; + va_start (args, msg_format); + mono_error_vset_type_load_class (oerror, klass, msg_format, args); + va_end (args); +} + +void +mono_error_vset_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, va_list args) { MonoErrorInternal *error = (MonoErrorInternal*)oerror; mono_error_prepare (error); error->error_code = MONO_ERROR_TYPE_LOAD; mono_error_set_class (oerror, klass); - set_error_message (); + set_error_messagev (); } /* @@ -463,6 +480,16 @@ mono_error_set_exception_instance (MonoError *oerror, MonoException *exc) error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE); } +void +mono_error_set_exception_handle (MonoError *oerror, MonoExceptionHandle exc) +{ + MonoErrorInternal *error = (MonoErrorInternal*)oerror; + + mono_error_prepare (error); + error->error_code = MONO_ERROR_EXCEPTION_INSTANCE; + error->exn.instance_handle = mono_gchandle_from_handle (MONO_HANDLE_CAST(MonoObject, exc), FALSE); +} + void mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...) { @@ -618,7 +645,7 @@ mono_error_prepare_exception (MonoError *oerror, MonoError *error_out) } exception = mono_exception_from_name_two_strings_checked (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name, error_out); - if (exception) + if (exception && error->full_message != NULL && strcmp (error->full_message, "")) set_message_on_exception (exception, error, error_out); } else { exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message); @@ -730,6 +757,9 @@ mono_error_convert_to_exception (MonoError *target_error) MonoError error; MonoException *ex; + /* Mempool stored error shouldn't be cleaned up */ + g_assert (!is_boxed ((MonoErrorInternal*)target_error)); + if (mono_error_ok (target_error)) return NULL; @@ -752,3 +782,97 @@ mono_error_move (MonoError *dest, MonoError *src) memcpy (dest, src, sizeof (MonoErrorInternal)); mono_error_init (src); } + +/** + * mono_error_box: + * @ierror: The input error that will be boxed. + * @image: The mempool of this image will hold the boxed error. + * + * Creates a new boxed error in the given mempool from MonoError. + * It does not alter ierror, so you still have to clean it up with + * mono_error_cleanup or mono_error_convert_to_exception or another such function. + * + * Returns the boxed error, or NULL if the mempool could not allocate. + */ +MonoErrorBoxed* +mono_error_box (const MonoError *ierror, MonoImage *image) +{ + MonoErrorInternal *from = (MonoErrorInternal*)ierror; + /* Don't know how to box a gchandle */ + g_assert (!is_managed_exception (from)); + MonoErrorBoxed* box = mono_image_alloc (image, sizeof (MonoErrorBoxed)); + box->image = image; + mono_error_init_flags (&box->error, MONO_ERROR_MEMPOOL_BOXED); + MonoErrorInternal *to = (MonoErrorInternal*)&box->error; + +#define DUP_STR(field) do { \ + if (from->field) { \ + if (!(to->field = mono_image_strdup (image, from->field))) \ + to->flags |= MONO_ERROR_INCOMPLETE; \ + } else { \ + to->field = NULL; \ + } \ + } while (0) + + to->error_code = from->error_code; + DUP_STR (type_name); + DUP_STR (assembly_name); + DUP_STR (member_name); + DUP_STR (exception_name_space); + DUP_STR (exception_name); + DUP_STR (full_message); + DUP_STR (full_message_with_fields); + DUP_STR (first_argument); + to->exn.klass = from->exn.klass; + +#undef DUP_STR + + return box; +} + + +/** + * mono_error_set_from_boxed: + * @oerror: The error that will be set to the contents of the box. + * @box: A mempool-allocated error. + * + * Sets the error condition in the oerror from the contents of the + * given boxed error. Does not alter the boxed error, so it can be + * used in a future call to mono_error_set_from_boxed as needed. The + * oerror should've been previously initialized with mono_error_init, + * as usual. + * + * Returns TRUE on success or FALSE on failure. + */ +gboolean +mono_error_set_from_boxed (MonoError *oerror, const MonoErrorBoxed *box) +{ + MonoErrorInternal* to = (MonoErrorInternal*)oerror; + MonoErrorInternal* from = (MonoErrorInternal*)&box->error; + g_assert (!is_managed_exception (from)); + + mono_error_prepare (to); + to->flags |= MONO_ERROR_FREE_STRINGS; +#define DUP_STR(field) do { \ + if (from->field) { \ + if (!(to->field = g_strdup (from->field))) \ + to->flags |= MONO_ERROR_INCOMPLETE; \ + } else { \ + to->field = NULL; \ + } \ + } while (0) + + to->error_code = from->error_code; + DUP_STR (type_name); + DUP_STR (assembly_name); + DUP_STR (member_name); + DUP_STR (exception_name_space); + DUP_STR (exception_name); + DUP_STR (full_message); + DUP_STR (full_message_with_fields); + DUP_STR (first_argument); + to->exn.klass = from->exn.klass; + +#undef DUP_STR + return (to->flags & MONO_ERROR_INCOMPLETE) == 0 ; +}