2010-07-10 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / mini / mini-darwin.c
index 6dcfd12ed85fdecafd71ce88fe9b425dab7d1a7d..f80cff8a7cba392e88bbe74d13e5d527db8bd761 100644 (file)
 #include <sys/time.h>
 #endif
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
-
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/loader.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/gc-internal.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/verify.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/metadata/attach.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
-#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/dtrace.h>
 
 #include <mach/exception.h>
 #include <mach/task.h>
 #include <pthread.h>
-
-#ifdef HAVE_SGEN_GC
-#undef pthread_create
-#undef pthread_join
-#undef pthread_detach
-#endif
+#include <dlfcn.h>
 
 /*
  * This code disables the CrashReporter of MacOS X by installing
@@ -189,11 +180,98 @@ macosx_register_exception_handler ()
                                            mach_exception_port,
                                            EXCEPTION_DEFAULT,
                                            MACHINE_THREAD_STATE) == KERN_SUCCESS);
+
+       mono_gc_register_mach_exception_thread (thread);
 }
 
+/* This is #define'd by Boehm GC to _GC_dlopen. */
+#undef dlopen
+
 void
 mono_runtime_install_handlers (void)
 {
        macosx_register_exception_handler ();
        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 ()
+{
+#if defined(__i386__)
+       /* Apple's fork syscall returns a regpair in EAX:EDX.
+        *  EAX == pid of caller always
+        *  EDX == 0 for parent, 1 for child
+        */             
+       register_t eax;
+       register_t edx;
+       pid_t pid;
+
+       __asm__  __volatile__ (
+               "mov $0x2, %%eax;"
+               "int $0x80;"
+               "mov %%eax, %0;"
+               "mov %%edx, %1;"
+               : "=m" (eax), "=m" (edx));
+
+       if (edx == 0) {
+               pid = eax;
+       } else if (edx == 1) {
+               pid = 0;
+       } else {
+               g_assert_not_reached ();
+       }
+
+       return pid;
+#else
+       g_assert_not_reached ();
+#endif
+}
+
+gboolean
+mono_gdb_render_native_backtraces ()
+{
+       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 FALSE;
+       }
+
+       if (mkstemp (gdb_template) != -1) {
+               FILE *gdb_commands = fopen (gdb_template, "w");
+
+               fprintf (gdb_commands, "attach %ld\n", (long) getpid ());
+               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);
+       }
+
+       return TRUE;
 }