X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-darwin.c;h=5ec06d20a748c8036e64b9900bbc623f3a47b723;hb=32455dbbe90d3f7826a2bae5a95360e050f04172;hp=6dcfd12ed85fdecafd71ce88fe9b425dab7d1a7d;hpb=c44dc12cb3e8a9a50981a5e112d1a64fa4fc3277;p=mono.git diff --git a/mono/mini/mini-darwin.c b/mono/mini/mini-darwin.c index 6dcfd12ed85..5ec06d20a74 100644 --- a/mono/mini/mini-darwin.c +++ b/mono/mini/mini-darwin.c @@ -5,7 +5,8 @@ * Mono Team (mono-list@lists.ximian.com) * * Copyright 2001-2003 Ximian, Inc. - * Copyright 2003-2008 Ximian, Inc. + * Copyright 2003-2011 Novell, Inc (http://www.novell.com) + * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) * * See LICENSE for licensing information. */ @@ -22,10 +23,6 @@ #include #endif -#ifdef HAVE_VALGRIND_MEMCHECK_H -#include -#endif - #include #include #include @@ -42,16 +39,16 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include -#include +#include #include #include @@ -69,13 +66,15 @@ #include #include #include +#include +#include -#ifdef HAVE_SGEN_GC -#undef pthread_create -#undef pthread_join -#undef pthread_detach +#if defined (TARGET_OSX) && (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5) +#define NEEDS_EXCEPTION_THREAD #endif +#ifdef NEEDS_EXCEPTION_THREAD + /* * This code disables the CrashReporter of MacOS X by installing * a dummy Mach exception handler. @@ -97,6 +96,15 @@ typedef struct { /* The exception port */ static mach_port_t mach_exception_port = VM_MAP_NULL; +kern_return_t +catch_exception_raise ( + mach_port_t exception_port, + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); + /* * Implicitly called by exc_server. Must be public. * @@ -150,13 +158,17 @@ mach_exception_thread (void *arg) MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); - g_assert (result == MACH_MSG_SUCCESS); + /* + If we try to abort the thread while delivering an exception. The port will be gone since the kernel + setup a send once port to deliver the resume message and thread_abort will consume it. + */ + g_assert (result == MACH_MSG_SUCCESS || result == MACH_SEND_INVALID_DEST); } return NULL; } static void -macosx_register_exception_handler () +macosx_register_exception_handler (void) { mach_port_t task; pthread_attr_t attr; @@ -189,11 +201,132 @@ macosx_register_exception_handler () mach_exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) == KERN_SUCCESS); + + mono_gc_register_mach_exception_thread (thread); } +#endif + +/* This is #define'd by Boehm GC to _GC_dlopen. */ +#undef dlopen + +void* dlopen(const char* path, int mode); + void mono_runtime_install_handlers (void) { +#ifdef NEEDS_EXCEPTION_THREAD macosx_register_exception_handler (); +#endif mono_runtime_posix_install_handlers (); + + /* Snow Leopard has a horrible bug: http://openradar.appspot.com/7209349 + * This causes obscure SIGTRAP's for any application that comes across this built on + * Snow Leopard. This is a horrible hack to ensure that the private __CFInitialize + * is run on the main thread, so that we don't get SIGTRAPs later + */ +#if defined (__APPLE__) && (defined (__i386__) || defined (__x86_64__)) + { + void *handle = dlopen ("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY); + if (handle == NULL) + return; + + dlclose (handle); + } +#endif +} + +pid_t +mono_runtime_syscall_fork () +{ + return (pid_t) fork (); +} + +void +mono_gdb_render_native_backtraces (pid_t crashed_pid) +{ + const char *argv [5]; + char gdb_template [] = "/tmp/mono-gdb-commands.XXXXXX"; + + argv [0] = g_find_program_in_path ("gdb"); + if (argv [0] == NULL) { + return; + } + + if (mkstemp (gdb_template) != -1) { + FILE *gdb_commands = fopen (gdb_template, "w"); + + fprintf (gdb_commands, "attach %ld\n", (long) crashed_pid); + fprintf (gdb_commands, "info threads\n"); + fprintf (gdb_commands, "thread apply all bt\n"); + + fflush (gdb_commands); + fclose (gdb_commands); + + argv [1] = "-batch"; + argv [2] = "-x"; + argv [3] = gdb_template; + argv [4] = 0; + + execv (argv [0], (char**)argv); + + unlink (gdb_template); + } +} + +gboolean +mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle) +{ + kern_return_t ret; + mach_msg_type_number_t num_state; + thread_state_t state; + ucontext_t ctx; + mcontext_t mctx; + guint32 domain_key, jit_key; + MonoJitTlsData *jit_tls; + void *domain; +#if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR) + guint32 lmf_key; +#endif + + /*Zero enough state to make sure the caller doesn't confuse itself*/ + tctx->valid = FALSE; + tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL; + tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL; + tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL; + + state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); + mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); + + ret = mono_mach_arch_get_thread_state (thread_handle, state, &num_state); + if (ret != KERN_SUCCESS) + return FALSE; + + mono_mach_arch_thread_state_to_mcontext (state, mctx); + ctx.uc_mcontext = mctx; + + mono_sigctx_to_monoctx (&ctx, &tctx->ctx); + + domain_key = mono_domain_get_tls_key (); + jit_key = mono_get_jit_tls_key (); + + jit_tls = mono_mach_arch_get_tls_value_from_thread (thread_id, jit_key); + domain = mono_mach_arch_get_tls_value_from_thread (thread_id, domain_key); + + /*Thread already started to cleanup, can no longer capture unwind state*/ + if (!jit_tls || !domain) + return FALSE; + +#if defined (MONO_ARCH_ENABLE_MONO_LMF_VAR) + lmf_key = mono_get_lmf_tls_offset (); + tctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_mach_arch_get_tls_value_from_thread (thread_id, lmf_key);; +#else + tctx->unwind_data [MONO_UNWIND_DATA_LMF] = jit_tls ? jit_tls->lmf : NULL; +#endif + + tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain; + tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls; + tctx->valid = TRUE; + + return TRUE; }