X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-exceptions.c;h=6cb5c2ac5178ae5556b13f60059378dc419661a3;hb=d0b97d4bd5f42978987b4ae1d7cad18bedd3b393;hp=76414e7691ebecdd3d368d5b1ba5553f7c72a6c6;hpb=d0baa99bcb8ef12231e24432d0b5710b3a0a4380;p=mono.git diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index 76414e7691e..6cb5c2ac517 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "mini.h" #include "debug-mini.h" @@ -541,6 +542,47 @@ get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info) return method; } +/** + * mono_exception_walk_native_trace: + * @ex: The exception object whose frames should be walked + * @func: callback to call for each stack frame + * @user_data: data passed to the callback + * + * This function walks the stacktrace of an exception. For + * each frame the callback function is called with the relevant info. + * The walk ends when no more stack frames are found or when the callback + * returns a TRUE value. + */ + +gboolean +mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data) +{ + MonoDomain *domain = mono_domain_get (); + MonoArray *ta = ex->trace_ips; + int len, i; + + if (ta == NULL) + return FALSE; + + len = mono_array_length (ta) >> 1; + for (i = 0; i < len; i++) { + gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0); + gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1); + MonoJitInfo *ji = mono_jit_info_table_find (domain, ip); + + if (ji == NULL) { + if (func (NULL, ip, 0, FALSE, user_data)) + return TRUE; + } else { + MonoMethod *method = get_method_from_stack_frame (ji, generic_info); + if (func (method, ji->code_start, (char *) ip - (char *) ji->code_start, TRUE, user_data)) + return TRUE; + } + } + + return len > 0; +} + MonoString * ves_icall_System_Exception_get_trace (MonoException *ex) { @@ -1366,7 +1408,9 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint3 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) { gboolean is_user_frame = ji->method->wrapper_type == MONO_WRAPPER_NONE || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD; +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->exceptions_filters++; +#endif mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), ex_obj); /* @@ -1560,7 +1604,7 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, mono_debugger_agent_handle_exception (obj, ctx, NULL); if (mini_get_debug_options ()->suspend_on_unhandled) { - fprintf (stderr, "Unhandled exception, suspending..."); + mono_runtime_printf_err ("Unhandled exception, suspending..."); while (1) ; } @@ -1723,7 +1767,9 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj); MONO_CONTEXT_SET_IP (ctx, ei->handler_start); *(mono_get_lmf_addr ()) = lmf; +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->exceptions_depth += frame_count; +#endif if (obj == domain->stack_overflow_ex) jit_tls->handling_stack_ovf = FALSE; @@ -1747,7 +1793,9 @@ mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, mono_profiler_exception_clause_handler (ji->method, ei->flags, i); jit_tls->orig_ex_ctx_set = FALSE; mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj); +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->exceptions_finallys++; +#endif *(mono_get_lmf_addr ()) = lmf; if (ji->from_llvm) { /* @@ -1900,7 +1948,9 @@ mono_debugger_run_finally (MonoContext *start_ctx) gboolean mono_handle_exception (MonoContext *ctx, gpointer obj) { +#ifndef DISABLE_PERFCOUNTERS mono_perfcounters->exceptions_thrown++; +#endif return mono_handle_exception_internal (ctx, obj, FALSE, NULL); } @@ -2084,7 +2134,7 @@ mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, /* We print a message: after this even managed stack overflows * may crash the runtime */ - fprintf (stderr, "Stack overflow in unmanaged: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), fault_addr); + mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr); if (!jit_tls->handling_stack_ovf) { jit_tls->restore_stack_prot = restore_stack_protection_tramp; jit_tls->handling_stack_ovf = 1; @@ -2098,7 +2148,6 @@ mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, } typedef struct { - FILE *stream; MonoMethod *omethod; int count; } PrintOverflowUserData; @@ -2108,7 +2157,6 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da { MonoMethod *method = NULL; PrintOverflowUserData *user_data = data; - FILE *stream = user_data->stream; gchar *location; if (frame->ji) @@ -2126,11 +2174,11 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da return FALSE; location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ()); - fprintf (stream, " %s\n", location); + mono_runtime_printf_err (" %s", location); g_free (location); if (user_data->count == 1) { - fprintf (stream, " <...>\n"); + mono_runtime_printf_err (" <...>"); user_data->omethod = method; } else { user_data->omethod = NULL; @@ -2138,7 +2186,7 @@ print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer da user_data->count ++; } else - fprintf (stream, " at <0x%05x>\n", frame->native_offset); + mono_runtime_printf_err (" at <0x%05x>", frame->native_offset); return FALSE; } @@ -2150,41 +2198,39 @@ mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, MonoContext mctx; /* we don't do much now, but we can warn the user with a useful message */ - fprintf (stderr, "Stack overflow: IP: %p, fault addr: %p\n", mono_arch_ip_from_context (ctx), fault_addr); + mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr); #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX mono_arch_sigctx_to_monoctx (ctx, &mctx); - fprintf (stderr, "Stacktrace:\n"); + mono_runtime_printf_err ("Stacktrace:"); memset (&ud, 0, sizeof (ud)); - ud.stream = stderr; mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud); #else if (ji && ji->method) - fprintf (stderr, "At %s\n", mono_method_full_name (ji->method, TRUE)); + mono_runtime_printf_err ("At %s", mono_method_full_name (ji->method, TRUE)); else - fprintf (stderr, "At .\n"); + mono_runtime_printf_err ("At ."); #endif _exit (1); } static gboolean -print_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data) +print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data) { - FILE *stream = (FILE*)data; MonoMethod *method = NULL; if (frame->ji) method = frame->ji->method; if (method) { gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ()); - fprintf (stream, " %s\n", location); + mono_runtime_printf_err (" %s", location); g_free (location); } else - fprintf (stream, " at <0x%05x>\n", frame->native_offset); + mono_runtime_printf_err (" at <0x%05x>", frame->native_offset); return FALSE; } @@ -2227,7 +2273,7 @@ mono_handle_native_sigsegv (int signal, void *ctx) return; if (mini_get_debug_options ()->suspend_on_sigsegv) { - fprintf (stderr, "Received SIGSEGV, suspending..."); + mono_runtime_printf_err ("Received SIGSEGV, suspending..."); while (1) ; } @@ -2237,11 +2283,9 @@ mono_handle_native_sigsegv (int signal, void *ctx) /* !jit_tls means the thread was not registered with the runtime */ if (jit_tls && mono_thread_internal_current ()) { - fprintf (stderr, "Stacktrace:\n\n"); - - mono_walk_stack (print_stack_frame, TRUE, stderr); + mono_runtime_printf_err ("Stacktrace:\n"); - fflush (stderr); + mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL); } #ifdef HAVE_BACKTRACE_SYMBOLS @@ -2251,17 +2295,15 @@ mono_handle_native_sigsegv (int signal, void *ctx) int i, size; const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT"; - fprintf (stderr, "\nNative stacktrace:\n\n"); + mono_runtime_printf_err ("\nNative stacktrace:\n"); size = backtrace (array, 256); names = backtrace_symbols (array, size); for (i =0; i < size; ++i) { - fprintf (stderr, "\t%s\n", names [i]); + mono_runtime_printf_err ("\t%s", names [i]); } free (names); - fflush (stderr); - /* Try to get more meaningful information using gdb */ #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork) @@ -2285,7 +2327,7 @@ mono_handle_native_sigsegv (int signal, void *ctx) exit (1); } - fprintf (stderr, "\nDebug info from gdb:\n\n"); + mono_runtime_printf_err ("\nDebug info from gdb:\n"); waitpid (pid, &status, 0); } #endif @@ -2294,14 +2336,14 @@ mono_handle_native_sigsegv (int signal, void *ctx) * on anything working. So try to print out lots of diagnostics, starting * with ones which have a greater chance of working. */ - fprintf (stderr, + mono_runtime_printf_err ( "\n" "=================================================================\n" "Got a %s while executing native code. This usually indicates\n" "a fatal error in the mono runtime or one of the native libraries \n" "used by your application.\n" - "=================================================================\n" - "\n", signal_str); + "=================================================================\n", + signal_str); } #endif @@ -2358,17 +2400,17 @@ mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx) mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text); #else - printf ("\t\n"); + mono_runtime_printf ("\t"); #endif - fprintf (stdout, "%s", text->str); + mono_runtime_printf ("%s", text->str); #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG OutputDebugStringA(text->str); #endif g_string_free (text, TRUE); - fflush (stdout); + mono_runtime_stdout_fflush (); } /* @@ -2658,12 +2700,15 @@ mono_invoke_unhandled_exception_hook (MonoObject *exc) MonoString *str = mono_object_to_string (exc, &other); if (str) { char *msg = mono_string_to_utf8 (str); - fprintf (stderr, "[ERROR] FATAL UNHANDLED EXCEPTION: %s\n", msg); - fflush (stderr); + mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg); g_free (msg); } +#if defined(__APPLE__) && defined(__arm__) + g_assertion_message ("Terminating runtime due to unhandled exception"); +#else exit (mono_environment_exitcode_get ()); +#endif } g_assert_not_reached ();