}
}
+static gboolean thread_dump_requested;
+
+static G_GNUC_UNUSED gboolean
+print_stack_frame_to_string (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
+{
+ GString *p = (GString*)data;
+ MonoMethod *method = NULL;
+ if (frame->ji)
+ method = frame->ji->method;
+
+ if (method) {
+ gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
+ g_string_append_printf (p, " %s\n", location);
+ g_free (location);
+ } else
+ g_string_append_printf (p, " at <unknown> <0x%05x>\n", frame->native_offset);
+
+ return FALSE;
+}
+
+static void
+print_thread_dump (MonoInternalThread *thread, MonoThreadInfo *info)
+{
+ GString* text = g_string_new (0);
+ char *name, *wapi_desc;
+ GError *error = NULL;
+
+ if (thread->name) {
+ name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
+ g_assert (!error);
+ g_string_append_printf (text, "\n\"%s\"", name);
+ g_free (name);
+ }
+ else if (thread->threadpool_thread)
+ g_string_append (text, "\n\"<threadpool thread>\"");
+ else
+ g_string_append (text, "\n\"<unnamed thread>\"");
+
+#if 0
+/* This no longer works with remote unwinding */
+#ifndef HOST_WIN32
+ wapi_desc = wapi_current_thread_desc ();
+ g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread, wapi_desc);
+ free (wapi_desc);
+#endif
+#endif
+
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (print_stack_frame_to_string, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, text);
+ mono_thread_info_resume (mono_thread_info_get_tid (info));
+
+ fprintf (stdout, "%s", text->str);
+
+#if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
+ OutputDebugStringA(text->str);
+#endif
+
+ g_string_free (text, TRUE);
+ fflush (stdout);
+}
+
+static void
+dump_thread (gpointer key, gpointer value, gpointer user)
+{
+ MonoInternalThread *thread = (MonoInternalThread *)value;
+ MonoThreadInfo *info;
+
+ if (thread == mono_thread_internal_current ())
+ return;
+
+ /*
+ FIXME This still can hang if we stop a thread during malloc.
+ FIXME This can hang if we suspend on a critical method and the GC kicks in. A fix might be to have function
+ that takes a callback and runs it with the target suspended.
+ We probably should loop a bit around trying to get it to either managed code
+ or WSJ state.
+ */
+ info = mono_thread_info_safe_suspend_sync ((pthread_t)(gpointer)(gsize)thread->tid, FALSE);
+
+ if (!info)
+ return;
+
+ print_thread_dump (thread, info);
+}
+
+void
+mono_threads_perform_thread_dump (void)
+{
+ if (!thread_dump_requested)
+ return;
+
+ printf ("Full thread dump:\n");
+
+ /*
+ * Make a copy of the hashtable since we can't do anything with
+ * threads while threads_mutex is held.
+ */
+ mono_threads_lock ();
+ mono_g_hash_table_foreach (threads, dump_thread, NULL);
+ mono_threads_unlock ();
+
+ thread_dump_requested = FALSE;
+}
+
/**
* mono_threads_request_thread_dump:
*
struct wait_data *wait = &wait_data;
int i;
+ /*The new thread dump code runs out of the finalizer thread. */
+ if (mono_thread_info_new_interrupt_enabled ()) {
+ thread_dump_requested = TRUE;
+ mono_gc_finalize_notify ();
+ return;
+ }
+
+
memset (wait, 0, sizeof (struct wait_data));
/*
if (res)
return;
- printf ("Full thread dump:\n");
+ if (mono_thread_info_new_interrupt_enabled ()) {
+ mono_threads_request_thread_dump ();
+ } else {
+ printf ("Full thread dump:\n");
- mono_threads_request_thread_dump ();
+ mono_threads_request_thread_dump ();
- /*
- * print_thread_dump () skips the current thread, since sending a signal
- * to it would invoke the signal handler below the sigquit signal handler,
- * and signal handlers don't create an lmf, so the stack walk could not
- * be performed.
- */
- mono_print_thread_dump (ctx);
+ /*
+ * print_thread_dump () skips the current thread, since sending a signal
+ * to it would invoke the signal handler below the sigquit signal handler,
+ * and signal handlers don't create an lmf, so the stack walk could not
+ * be performed.
+ */
+ mono_print_thread_dump (ctx);
+ }
mono_chain_signal (SIG_HANDLER_PARAMS);
}