2002-05-14 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 14 May 2002 10:08:21 +0000 (10:08 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 14 May 2002 10:08:21 +0000 (10:08 -0000)
* object.c (mono_runtime_invoke): is now able to catch exceptions.

svn path=/trunk/mono/; revision=4618

13 files changed:
mono/interpreter/interp.c
mono/jit/delegate.c
mono/jit/exception.c
mono/jit/invoke.c
mono/jit/jit.c
mono/jit/jit.h
mono/metadata/ChangeLog
mono/metadata/appdomain.c
mono/metadata/gc.c
mono/metadata/icall.c
mono/metadata/object.c
mono/metadata/object.h
mono/metadata/reflection.c

index afa7b9e201693dc4d1bb651dd6cf71655503d3f8..b11dd826327b619207be003fa58d8d6158ac3b12 100644 (file)
@@ -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
index d350ec14759376a21fe3a4a4be509921f3ee978e..a203c79827e4f1c7516160638cecbdf7247a4921 100644 (file)
@@ -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);
        }
 }
 
index 45699a9199a20751db031fc89532a2e578cdcc02..1dac4bda09884bf52496da23c6a10e1ed24efc21 100644 (file)
@@ -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 ();
        
index 29f693b4b2b1f9fa633a728abd472e01a4793ec2..345e8aa360983cf59cc9de8f67ad0f1d72e5bd47 100644 (file)
@@ -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;
 }
 
index 777433f301ce2ca64df61cd113b991f65663a677..d68eba414635bafc4ea086f4c106ad938d5c5199 100644 (file)
@@ -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);
 
index c1b0c51d5203273c9d13c55800e5af90cd2d7b3d..87f0cc92b146905bad6d3238829df0c67e3c9250 100644 (file)
@@ -21,6 +21,7 @@
 #include <signal.h>
 #endif
 
+#include <setjmp.h>
 #include <mono/metadata/loader.h>
 #include <mono/metadata/object.h>
 #include <mono/metadata/exception.h>
@@ -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);
index 87887a4742d8db2772c056fe4430f7aa3ef68669..ad47ce08e3eb485c7cf1acf77a47d178099d4626 100644 (file)
@@ -1,5 +1,7 @@
 2002-05-14  Dietmar Maurer  <dietmar@ximian.com>
 
+       * 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.
 
index 209ec01a1cdaa5eeb022905f3c8b28fe274ca348..57820053ecb3c41c230ae78002b2e8f7d720386e 100644 (file)
@@ -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);
 
index 3ce1f1d4061b38c582328b22b341f346ca0b1c88..b5ecc27a7343851923a447c4657bad0e54d87407 100644 (file)
@@ -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 */
+        }
 }
 
 /*
index b86ae1d05bf5594c7a88c122865c1908d28fae1d..4fbb9c192522eb167538a6a3f2e2b8f61e8bae17 100644 (file)
@@ -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();
index 5f623d60c0d9c8750976da8969551eeb48cdfca1..a791f0a2efda3f11b4fc6b9b79a7afcf09b06c70 100644 (file)
@@ -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);
+}
+
 
 
index f810e49391b9a2a8f0a83ee65f7b25925280f045..3374b431fad40de947e441afd7870536baa1eb21 100644 (file)
@@ -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
 
index 2a795b7aabe264dbc58e3b01e0a7328e856c3aa1..8879597fced97d1fbeb570d6ffe6a07f91284135 100644 (file)
@@ -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);