* object.c (mono_runtime_invoke): is now able to catch exceptions.
svn path=/trunk/mono/; revision=4618
(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;
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);
}
}
- 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
/* 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);
}
}
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 ();
* 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;
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;
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;
}
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
g_error ("we should never reach this code");
}
-static guint32 mono_main_thread_id = 0;
-
/**
* mono_thread_abort:
* @obj: exception object
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);
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);
}
TlsSetValue (mono_jit_tls_id, jit_tls);
- jit_tls->end_of_stack = stack_start;
jit_tls->abort_func = mono_thread_abort;
}
metadata_section = &ms;
InitializeCriticalSection (metadata_section);
- mono_main_thread_id = GetCurrentThreadId ();
-
mono_jit_tls_id = TlsAlloc ();
mono_thread_start_cb (&file);
#include <signal.h>
#endif
+#include <setjmp.h>
#include <mono/metadata/loader.h>
#include <mono/metadata/object.h>
#include <mono/metadata/exception.h>
typedef struct {
gpointer end_of_stack;
+ jmp_buf *env;
MonoLMF *lmf;
MonoAsyncResult *async_result;
void (*abort_func) (MonoObject *object);
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);
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.
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);
static void
run_finalize (void *obj, void *data)
{
+ MonoObject *exc = NULL;
MonoObject *o;
o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (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 */
+ }
}
/*
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 *
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;
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();
MonoStats mono_stats;
-/* next object id for object hashcode */
-static guint32 uoid = 0;
-
void
mono_runtime_object_init (MonoObject *this)
{
g_assert (method);
- mono_runtime_invoke (method, this, NULL);
+ mono_runtime_invoke (method, this, NULL, NULL);
}
/*
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;
}
}
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;
* 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;
}
}
- return mono_runtime_exec_main (method, args);
+ return mono_runtime_exec_main (method, args, exc);
}
/*
* 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
}
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;
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);
}
/**
pa [2] = exc;
pa [3] = out_args;
- return mono_runtime_invoke (im, NULL, pa);
+ return mono_runtime_invoke (im, NULL, pa, exc);
}
MonoObject *
}
}
- 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);
+}
+
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)
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,
mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
MonoObject **exc, MonoArray **out_args);
+void
+mono_print_unhandled_exception (MonoObject *exc);
+
#endif
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);