In man:
authorRolf Bjarne Kvinge <RKvinge@novell.com>
Wed, 3 Mar 2010 09:25:00 +0000 (09:25 -0000)
committerRolf Bjarne Kvinge <RKvinge@novell.com>
Wed, 3 Mar 2010 09:25:00 +0000 (09:25 -0000)
2010-03-03  Rolf Bjarne Kvinge  <RKvinge@novell.com>

* mono.1: Document exception tracing.

In mono/mini:
2010-03-03  Rolf Bjarne Kvinge  <RKvinge@novell.com>

* trace.c|h:
* mini-exceptions.c: Add support for printing stack traces when handling
exceptions, and when printing exceptions thrown while tracing also print
the exception message.

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

man/ChangeLog
man/mono.1
mono/mini/ChangeLog
mono/mini/mini-exceptions.c
mono/mini/trace.c
mono/mini/trace.h

index a2b919eacdf4f78a2598a8e6cdd65955420ae5ea..e0a3ab437ab7bcbcb984b1cad0e89389aa19b822 100644 (file)
@@ -1,3 +1,7 @@
+2010-03-03  Rolf Bjarne Kvinge  <RKvinge@novell.com>
+
+       * mono.1: Document exception tracing.
+
 2010-02-18  Marek Habersack  <mhabersack@novell.com>
 
        * mono-configuration-crypto.1: added
index 0c73301105d91274c57a5f14071570f993997814..ea99ab88a703c647f55b1e62bdf61efc244be39f 100644 (file)
@@ -426,6 +426,15 @@ standard method notation:
 
        mono --trace=M:System.Console:WriteLine app.exe
 
+.fi
+Exceptions can also be traced, it will cause a stack trace to be
+printed every time an exception of the specified type is thrown.
+The exception type can be specified with or without the namespace,
+and to trace all exceptions, specify 'all' as the type name.
+.nf
+
+       mono --trace=E:System.Exception app.exe
+
 .fi
 As previously noted, various rules can be specified at once:
 .nf
index d92fb702b1cdac4600a1eab5a219a4bebf5fa54b..6c902d48e32015044d98c2a477bc160208ecf2f5 100755 (executable)
@@ -1,3 +1,10 @@
+2010-03-03  Rolf Bjarne Kvinge  <RKvinge@novell.com>
+
+       * trace.c|h:
+       * mini-exceptions.c: Add support for printing stack traces when handling
+       exceptions, and when printing exceptions thrown while tracing also print
+       the exception message.
+
 2010-03-03  Rolf Bjarne Kvinge  <RKvinge@novell.com>
 
        * trace.c: We need to parse exclude tokens ('-') before string tokens,
index 092a3ec658c02293a159ee5bd6cfa21d197b20be..fa2ab771e2b9b61712391b06a9c3faef1879e10f 100644 (file)
@@ -1189,8 +1189,30 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gpointer origina
 
        if (!test_only) {
                MonoContext ctx_cp = *ctx;
-               if (mono_trace_is_enabled ())
-                       g_print ("[%p:] EXCEPTION handling: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name);
+               if (mono_trace_is_enabled ()) {
+                       MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
+                       MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
+                       MonoObject *message;
+                       const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
+                       char *msg = NULL;
+                       MonoObject *exc = NULL;
+                       if (get_message == NULL) {
+                               message = NULL;
+                       } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
+                               message = NULL;
+                               msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
+                       } else {
+                               message = mono_runtime_invoke (get_message, obj, NULL, &exc);
+                               
+                       }
+                       if (msg == NULL) {
+                               msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
+                       }
+                       g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
+                       g_free (msg);
+                       if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
+                               mono_print_thread_dump_from_ctx (ctx);
+               }
                mono_profiler_exception_thrown (obj);
                if (!mono_handle_exception_internal (&ctx_cp, obj, original_ip, TRUE, FALSE, &first_filter_idx, out_ji)) {
                        if (mono_break_on_exc)
index f76d32473c8c744ff68069decf44059849d629c1..6348a434fb22abb8e9ec44cdf7038c126271dbb9 100644 (file)
 
 static MonoTraceSpec trace_spec;
 
+gboolean
+mono_trace_eval_exception (MonoClass *klass)
+{
+       int include = 0;
+       int i;
+
+       if (!klass)
+               return FALSE;
+
+       for (i = 0; i < trace_spec.len; i++) {
+               MonoTraceOperation *op = &trace_spec.ops [i];
+               int inc = 0;
+               
+               switch (op->op){
+               case MONO_TRACEOP_EXCEPTION:
+                       if (strcmp ("", op->data) == 0 && strcmp ("all", op->data2) == 0)
+                               inc = 1;
+                       else if (strcmp ("", op->data) == 0 || strcmp (klass->name_space, op->data) == 0)
+                               if (strcmp (klass->name, op->data2) == 0)
+                                       inc = 1;
+                       break;
+               default:
+                       break;
+               }
+               if (op->exclude){
+                       if (inc)
+                               include = 0;
+               } else if (inc)
+                       include = 1;
+       }
+
+       return include;
+}
+
 gboolean
 mono_trace_eval (MonoMethod *method)
 {
@@ -55,6 +89,8 @@ mono_trace_eval (MonoMethod *method)
                case MONO_TRACEOP_NAMESPACE:
                        if (strcmp (method->klass->name_space, op->data) == 0)
                                inc = 1;
+               case MONO_TRACEOP_EXCEPTION:
+                       break;
                }
                if (op->exclude){
                        if (inc)
@@ -99,6 +135,7 @@ enum Token {
        TOKEN_CLASS,
        TOKEN_ALL,
        TOKEN_PROGRAM,
+       TOKEN_EXCEPTION,
        TOKEN_NAMESPACE,
        TOKEN_STRING,
        TOKEN_EXCLUDE,
@@ -132,6 +169,11 @@ get_token (void)
                get_string ();
                return TOKEN_CLASS;
        }
+       if (input [0] == 'E' && input [1] == ':'){
+               input += 2;
+               get_string ();
+               return TOKEN_EXCEPTION;
+       }
        if (*input == '-'){
                input++;
                return TOKEN_EXCLUDE;
@@ -195,7 +237,7 @@ get_spec (int *last)
        else if (token == TOKEN_NAMESPACE){
                trace_spec.ops [*last].op = MONO_TRACEOP_NAMESPACE;
                trace_spec.ops [*last].data = g_strdup (value);
-       } else if (token == TOKEN_CLASS){
+       } else if (token == TOKEN_CLASS || token == TOKEN_EXCEPTION){
                char *p = strrchr (value, '.');
                if (p) {
                        *p++ = 0;
@@ -206,7 +248,7 @@ get_spec (int *last)
                        trace_spec.ops [*last].data = g_strdup ("");
                        trace_spec.ops [*last].data2 = g_strdup (value);
                }
-               trace_spec.ops [*last].op = MONO_TRACEOP_CLASS;
+               trace_spec.ops [*last].op = token == TOKEN_CLASS ? MONO_TRACEOP_CLASS : MONO_TRACEOP_EXCEPTION;
        } else if (token == TOKEN_STRING){
                trace_spec.ops [*last].op = MONO_TRACEOP_ASSEMBLY;
                trace_spec.ops [*last].data = g_strdup (value);
@@ -613,4 +655,3 @@ mono_trace_is_enabled ()
 {
        return trace_spec.enabled;
 }
-
index 6ef4c6471b6be5cdd89e01ba1de636e29f97b5af..6f6d3a0dcac4aa3215d618d84d670901d38f8c8c 100644 (file)
@@ -9,7 +9,8 @@ typedef enum {
        MONO_TRACEOP_METHOD,
        MONO_TRACEOP_ASSEMBLY,
        MONO_TRACEOP_CLASS,
-       MONO_TRACEOP_NAMESPACE
+       MONO_TRACEOP_NAMESPACE,
+       MONO_TRACEOP_EXCEPTION,
 } MonoTraceOpcode;
 
 typedef struct {
@@ -36,6 +37,7 @@ mono_trace_leave_method (MonoMethod *method, ...) MONO_INTERNAL;
 
 void mono_trace_enable (gboolean enable) MONO_INTERNAL;
 gboolean mono_trace_is_enabled (void) MONO_INTERNAL;
+gboolean mono_trace_eval_exception (MonoClass *klass) MONO_INTERNAL;
 
 G_END_DECLS