From 7cb732d788da5d938849e8f923efeb1672460761 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Tue, 14 May 2002 10:08:21 +0000 Subject: [PATCH] 2002-05-14 Dietmar Maurer * object.c (mono_runtime_invoke): is now able to catch exceptions. svn path=/trunk/mono/; revision=4618 --- mono/interpreter/interp.c | 13 +++++-- mono/jit/delegate.c | 2 +- mono/jit/exception.c | 5 +-- mono/jit/invoke.c | 24 ++++++++++++- mono/jit/jit.c | 41 ++++++++-------------- mono/jit/jit.h | 4 ++- mono/metadata/ChangeLog | 2 ++ mono/metadata/appdomain.c | 2 +- mono/metadata/gc.c | 7 +++- mono/metadata/icall.c | 8 ++--- mono/metadata/object.c | 72 ++++++++++++++++++++++++++++---------- mono/metadata/object.h | 17 ++++++--- mono/metadata/reflection.c | 2 +- 13 files changed, 133 insertions(+), 66 deletions(-) diff --git a/mono/interpreter/interp.c b/mono/interpreter/interp.c index afa7b9e2016..b11dd826327 100644 --- a/mono/interpreter/interp.c +++ b/mono/interpreter/interp.c @@ -904,7 +904,8 @@ verify_method (MonoMethod *m) (guint64)(MYGUINT64_MAX) - (guint64)(b) < (guint64)(a) ? -1 : 0 static MonoObject* -interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params) +interp_mono_runtime_invoke (MonoMethod *method, void *obj, void **params, + MonoObject **exc) { MonoInvocation frame; MonoObject *retval = NULL; @@ -3817,7 +3818,8 @@ ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]) MonoImage *image = assembly->image; MonoCLIImageInfo *iinfo; MonoMethod *method; - int i; + MonoObject *exc = NULL; + int i, rval; iinfo = image->image_info; method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL); @@ -3832,7 +3834,12 @@ ves_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]) } } - return mono_runtime_exec_main (method, args); + rval = mono_runtime_exec_main (method, args, &exc); + + if (exc) + mono_print_unhandled_exception (exc); + + return rval; } static void diff --git a/mono/jit/delegate.c b/mono/jit/delegate.c index d350ec14759..a203c79827e 100644 --- a/mono/jit/delegate.c +++ b/mono/jit/delegate.c @@ -101,7 +101,7 @@ mono_async_invoke (MonoAsyncResult *ares, gboolean cb_only) /* call async callback if cb_method != null*/ if (ac->cb_method) { void *pa = &ares; - mono_runtime_invoke (ac->cb_method, ac->cb_target, pa); + mono_runtime_invoke (ac->cb_method, ac->cb_target, pa, NULL); } } diff --git a/mono/jit/exception.c b/mono/jit/exception.c index 45699a9199a..1dac4bda098 100644 --- a/mono/jit/exception.c +++ b/mono/jit/exception.c @@ -154,9 +154,10 @@ arch_handle_exception (struct sigcontext *ctx, gpointer obj) g_assert (obj != NULL); ji = mono_jit_info_table_find (domain, ip); - + end_of_stack = jit_tls->end_of_stack; - + g_assert (end_of_stack); + if (!restore_context) restore_context = arch_get_restore_context (); diff --git a/mono/jit/invoke.c b/mono/jit/invoke.c index 29f693b4b2b..345e8aa3609 100644 --- a/mono/jit/invoke.c +++ b/mono/jit/invoke.c @@ -92,10 +92,11 @@ get_invoke_method_with_frame (void) * trampoline (as suggested by Paolo). */ MonoObject* -arch_runtime_invoke (MonoMethod *method, void *obj, void **params) +arch_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc) { static guint64 (*invoke_int64) (gpointer code, gpointer frame, int frame_size) = NULL; static double (*invoke_double) (gpointer code, gpointer frame, int frame_size) = NULL; + MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); MonoObject *retval; MonoMethodSignature *sig; int i, tmp, type, sp = 0; @@ -103,9 +104,25 @@ arch_runtime_invoke (MonoMethod *method, void *obj, void **params) int frame_size = 0; gpointer *frame; gpointer code; + gpointer last_end_of_stack; + jmp_buf env, *last_env; sig = method->signature; + if (exc) { + last_end_of_stack = jit_tls->end_of_stack; + last_env = jit_tls->env; + + jit_tls->end_of_stack = &last_env; + jit_tls->env = &env; + + if ((*exc = setjmp (env))) { + jit_tls->end_of_stack = last_end_of_stack; + jit_tls->env = last_env; + return NULL; + } + } + /* allocate ret object. */ if (sig->ret->type == MONO_TYPE_VOID) { retval = NULL; @@ -255,6 +272,11 @@ handle_enum_2: g_error ("return type 0x%x not handled in arch_runtime_invoke", type); } + if (exc) { + jit_tls->end_of_stack = last_end_of_stack; + jit_tls->env = last_env; + } + return retval; } diff --git a/mono/jit/jit.c b/mono/jit/jit.c index 777433f301c..d68eba41463 100644 --- a/mono/jit/jit.c +++ b/mono/jit/jit.c @@ -3655,11 +3655,18 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[ MonoImage *image = assembly->image; MonoCLIImageInfo *iinfo; MonoMethod *method; + MonoObject *exc; + int rval; iinfo = image->image_info; method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL); - return mono_runtime_run_main (method, argc, argv); + rval = mono_runtime_run_main (method, argc, argv, &exc); + + if (exc) + mono_print_unhandled_exception (exc); + + return rval; } #ifdef PLATFORM_WIN32 @@ -3710,8 +3717,6 @@ sigsegv_signal_handler (int _dummy) g_error ("we should never reach this code"); } -static guint32 mono_main_thread_id = 0; - /** * mono_thread_abort: * @obj: exception object @@ -3721,21 +3726,16 @@ static guint32 mono_main_thread_id = 0; static void mono_thread_abort (MonoObject *obj) { - const char *message = ""; - char *trace = NULL; - MonoString *str; + MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); + MonoDomain *domain = mono_domain_get (); MonoClassField *field; MonoDelegate *d; - MonoDomain *domain = mono_domain_get (); - + g_assert (obj); - if (mono_object_isinst (obj, mono_defaults.exception_class)) { - if ((str = ((MonoException *)obj)->message)) - message = mono_string_to_utf8 (str); - if ((str = ((MonoException *)obj)->stack_trace)) - trace = mono_string_to_utf8 (str); - } + if (jit_tls->env) { + longjmp (*jit_tls->env, obj); + } field=mono_class_get_field_from_name(mono_defaults.appdomain_class, "UnhandledException"); g_assert (field); @@ -3744,20 +3744,12 @@ mono_thread_abort (MonoObject *obj) d = *(MonoDelegate **)(((char *)domain->domain) + field->offset); if (!d) { - g_warning ("unhandled exception %s.%s: \"%s\"", obj->vtable->klass->name_space, - obj->vtable->klass->name, message); - if (trace) { - g_printerr (trace); - g_printerr ("\n"); - } + mono_print_unhandled_exception (obj); } else { /* FIXME: call the event handler */ g_assert_not_reached (); } - - if (mono_main_thread_id == GetCurrentThreadId ()) - mono_delegate_cleanup (); ExitThread (-1); } @@ -3771,7 +3763,6 @@ mono_thread_start_cb (gpointer stack_start) TlsSetValue (mono_jit_tls_id, jit_tls); - jit_tls->end_of_stack = stack_start; jit_tls->abort_func = mono_thread_abort; } @@ -3821,8 +3812,6 @@ mono_jit_init (char *file) { metadata_section = &ms; InitializeCriticalSection (metadata_section); - mono_main_thread_id = GetCurrentThreadId (); - mono_jit_tls_id = TlsAlloc (); mono_thread_start_cb (&file); diff --git a/mono/jit/jit.h b/mono/jit/jit.h index c1b0c51d520..87f0cc92b14 100644 --- a/mono/jit/jit.h +++ b/mono/jit/jit.h @@ -21,6 +21,7 @@ #include #endif +#include #include #include #include @@ -197,6 +198,7 @@ typedef struct { typedef struct { gpointer end_of_stack; + jmp_buf *env; MonoLMF *lmf; MonoAsyncResult *async_result; void (*abort_func) (MonoObject *object); @@ -261,7 +263,7 @@ gpointer arch_create_remoting_trampoline (MonoMethod *method); MonoObject* -arch_runtime_invoke (MonoMethod *method, void *obj, void **params); +arch_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc); gpointer arch_create_native_wrapper (MonoMethod *method); diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 87887a4742d..ad47ce08e3e 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,5 +1,7 @@ 2002-05-14 Dietmar Maurer + * object.c (mono_runtime_invoke): is now able to catch exceptions. + * threads.c (mono_thread_init): added a callback which is invoked at thread start. diff --git a/mono/metadata/appdomain.c b/mono/metadata/appdomain.c index 209ec01a1cd..57820053ecb 100644 --- a/mono/metadata/appdomain.c +++ b/mono/metadata/appdomain.c @@ -366,7 +366,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, g_error ("No entry point method found in %s", image->name); margs = mono_domain_transfer_object (cdom, ad->data, (MonoObject *)args); - res = mono_runtime_exec_main (method, (MonoArray *)margs); + res = mono_runtime_exec_main (method, (MonoArray *)margs, NULL); mono_domain_set (cdom); diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 3ce1f1d4061..b5ecc27a734 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -24,6 +24,7 @@ static int finalize_slot = -1; static void run_finalize (void *obj, void *data) { + MonoObject *exc = NULL; MonoObject *o; o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data)); @@ -39,7 +40,11 @@ run_finalize (void *obj, void *data) } } /* speedup later... */ - mono_runtime_invoke (o->vtable->klass->vtable [finalize_slot], o, NULL); + mono_runtime_invoke (o->vtable->klass->vtable [finalize_slot], o, NULL, &exc); + + if (exc) { + /* fixme: do something useful */ + } } /* diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index b86ae1d05bf..4fbb9c19252 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -951,7 +951,7 @@ ves_icall_get_type_info (MonoType *type, MonoTypeInfo *info) static MonoObject * ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params) { - return mono_runtime_invoke_array (method->method, this, params); + return mono_runtime_invoke_array (method->method, this, params, NULL); } static MonoObject * @@ -1046,7 +1046,7 @@ ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoA if (!strcmp (method->method->name, ".ctor")) g_assert_not_reached (); - result = mono_runtime_invoke_array (method->method, this, params); + result = mono_runtime_invoke_array (method->method, this, params, NULL); *outArgs = out_args; @@ -2126,13 +2126,11 @@ ves_icall_System_Environment_GetEnvironmentVariableNames (void) return names; } -int ves_icall_System_Environment_get_TickCount (void); - /* * Returns the number of milliseconds elapsed since the system started. */ static gint32 -ves_icall_System_Environment_get_TickCount () +ves_icall_System_Environment_get_TickCount (void) { #if defined (PLATFORM_WIN32) return GetTickCount(); diff --git a/mono/metadata/object.c b/mono/metadata/object.c index 5f623d60c0d..a791f0a2efd 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -24,9 +24,6 @@ MonoStats mono_stats; -/* next object id for object hashcode */ -static guint32 uoid = 0; - void mono_runtime_object_init (MonoObject *this) { @@ -44,7 +41,7 @@ mono_runtime_object_init (MonoObject *this) g_assert (method); - mono_runtime_invoke (method, this, NULL); + mono_runtime_invoke (method, this, NULL, NULL); } /* @@ -62,7 +59,7 @@ mono_runtime_class_init (MonoClass *klass) MonoMethod *method = klass->methods [i]; if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && (strcmp (".cctor", method->name) == 0)) { - mono_runtime_invoke (method, NULL, NULL); + mono_runtime_invoke (method, NULL, NULL, NULL); return; } } @@ -305,13 +302,13 @@ mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class) static MonoInvokeFunc default_mono_runtime_invoke = NULL; MonoObject* -mono_runtime_invoke (MonoMethod *method, void *obj, void **params) +mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc) { if (!default_mono_runtime_invoke) { g_error ("runtime invoke called on uninitialized runtime"); return NULL; } - return default_mono_runtime_invoke (method, obj, params); + return default_mono_runtime_invoke (method, obj, params, exc); } static MonoArray* main_args; @@ -328,7 +325,8 @@ mono_runtime_get_main_args (void) * needed by System.Environment. */ int -mono_runtime_run_main (MonoMethod *method, int argc, char* argv[]) +mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], + MonoObject **exc) { int i; MonoArray *args = NULL; @@ -349,7 +347,7 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[]) } } - return mono_runtime_exec_main (method, args); + return mono_runtime_exec_main (method, args, exc); } /* @@ -357,21 +355,30 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[]) * executable name). */ int -mono_runtime_exec_main (MonoMethod *method, MonoArray *args) +mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc) { gpointer pa [1]; + int rval; pa [0] = args; /* FIXME: check signature of method */ if (method->signature->ret->type == MONO_TYPE_I4) { MonoObject *res; - res = mono_runtime_invoke (method, NULL, pa); - return *(guint32 *)((char *)res + sizeof (MonoObject)); + res = mono_runtime_invoke (method, NULL, pa, exc); + if (!exc || !*exc) + rval = *(guint32 *)((char *)res + sizeof (MonoObject)); + else + rval = -1; } else { - mono_runtime_invoke (method, NULL, pa); - return 0; + mono_runtime_invoke (method, NULL, pa, exc); + if (!exc || !*exc) + rval = 0; + else + rval = -1; } + + return rval; } void @@ -381,7 +388,8 @@ mono_install_runtime_invoke (MonoInvokeFunc func) } MonoObject* -mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params) +mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, + MonoObject **exc) { MonoMethodSignature *sig = method->signature; gpointer *pa = NULL; @@ -423,10 +431,10 @@ mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params) if (!strcmp (method->name, ".ctor")) { obj = mono_object_new (mono_domain_get (), method->klass); - mono_runtime_invoke (method, obj, pa); + mono_runtime_invoke (method, obj, pa, exc); return obj; } else - return mono_runtime_invoke (method, obj, pa); + return mono_runtime_invoke (method, obj, pa, exc); } /** @@ -1201,7 +1209,7 @@ mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg, pa [2] = exc; pa [3] = out_args; - return mono_runtime_invoke (im, NULL, pa); + return mono_runtime_invoke (im, NULL, pa, exc); } MonoObject * @@ -1236,9 +1244,35 @@ mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, } } - return mono_runtime_invoke_array (method, target, msg->args); + return mono_runtime_invoke_array (method, target, msg->args, exc); } } +void +mono_print_unhandled_exception (MonoObject *exc) +{ + char *message = g_strdup (""); + char *trace = g_strdup (""); + MonoString *str; + + if (mono_object_isinst (exc, mono_defaults.exception_class)) { + if ((str = ((MonoException *)exc)->message)) + message = mono_string_to_utf8 (str); + if ((str = ((MonoException *)exc)->stack_trace)) + trace = mono_string_to_utf8 (str); + } + + g_warning ("unhandled exception %s.%s: \"%s\"", exc->vtable->klass->name_space, + exc->vtable->klass->name, message); + + if (trace) { + g_printerr (trace); + g_printerr ("\n"); + } + + g_free (message); + g_free (trace); +} + diff --git a/mono/metadata/object.h b/mono/metadata/object.h index f810e49391b..3374b431fad 100644 --- a/mono/metadata/object.h +++ b/mono/metadata/object.h @@ -153,7 +153,7 @@ typedef struct { gulong class_static_data_size; } MonoStats; -typedef MonoObject* (*MonoInvokeFunc) (MonoMethod *method, void *obj, void **params); +typedef MonoObject* (*MonoInvokeFunc) (MonoMethod *method, void *obj, void **params, MonoObject **exc); #define mono_object_class(obj) (((MonoObject*)(obj))->vtable->klass) #define mono_object_domain(obj) (((MonoObject*)(obj))->vtable->domain) @@ -258,19 +258,23 @@ void mono_install_runtime_invoke (MonoInvokeFunc func); MonoObject* -mono_runtime_invoke (MonoMethod *method, void *obj, void **params); +mono_runtime_invoke (MonoMethod *method, void *obj, void **params, + MonoObject **exc); MonoObject* -mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params); +mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params, + MonoObject **exc); MonoArray* mono_runtime_get_main_args (void); int -mono_runtime_run_main (MonoMethod *method, int argc, char* argv[]); +mono_runtime_run_main (MonoMethod *method, int argc, char* argv[], + MonoObject **exc); int -mono_runtime_exec_main (MonoMethod *method, MonoArray *args); +mono_runtime_exec_main (MonoMethod *method, MonoArray *args, + MonoObject **exc); MonoAsyncResult * mono_async_result_new (MonoDomain *domain, HANDLE handle, @@ -291,5 +295,8 @@ MonoObject * mono_message_invoke (MonoObject *target, MonoMethodMessage *msg, MonoObject **exc, MonoArray **out_args); +void +mono_print_unhandled_exception (MonoObject *exc); + #endif diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 2a795b7aabe..8879597fced 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -2891,7 +2891,7 @@ mono_reflection_get_custom_attrs (MonoObject *obj) params = g_new (void*, method->signature->param_count); fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params); attr = mono_object_new (mono_domain_get (), method->klass); - mono_runtime_invoke (method, attr, params); + mono_runtime_invoke (method, attr, params, NULL); list = g_list_prepend (list, attr); free_param_data (method->signature, params); g_free (params); -- 2.25.1