From a04e69b4454d5033fa42303477410b04aa93dca3 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 15 Jul 2019 11:58:04 -0300 Subject: [PATCH] [debugger] Don't list finalizer gc thread if it's not executing managed code (mono/mono#15618) * The example that reproduces the bug does this: var thread = vm.GetThreads()[0]; greetingValue = program.InvokeMethod(thread, greeting, new Value[0]) as StringMirror; But sometimes the Thread[0] was the MainThread of the program and it works, and other times was the GC Finalizer, but when it tries to run something on GC Finalizer thread, the thread is not suspended and throws an exception. In the fix I removed the Finalizer thread if it's not executing a managed code of the list that is returned when CMD_VM_ALL_THREADS is called. Fix mono/mono#13311 Commit migrated from https://github.com/mono/mono/commit/73128453daff8966f1c8eeacb734579971b02218 --- src/mono/mono/mini/debugger-agent.c | 68 ++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/mini/debugger-agent.c b/src/mono/mono/mini/debugger-agent.c index 637894c..5d65657 100644 --- a/src/mono/mono/mini/debugger-agent.c +++ b/src/mono/mono/mini/debugger-agent.c @@ -262,6 +262,8 @@ struct _DebuggerTlsData { // The state that the debugger expects the thread to be in MonoDebuggerThreadState thread_state; MonoStopwatch step_time; + + gboolean gc_finalizing; }; typedef struct { @@ -665,6 +667,10 @@ static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly); static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly); +static void gc_finalizing (MonoProfiler *prof); + +static void gc_finalized (MonoProfiler *prof); + static void emit_assembly_load (gpointer assembly, gpointer user_data); static void emit_type_load (gpointer key, gpointer type, gpointer user_data); @@ -974,7 +980,9 @@ debugger_agent_init (void) mono_profiler_set_assembly_unloading_callback (prof, assembly_unload); mono_profiler_set_jit_done_callback (prof, jit_done); mono_profiler_set_jit_failed_callback (prof, jit_failed); - + mono_profiler_set_gc_finalizing_callback (prof, gc_finalizing); + mono_profiler_set_gc_finalized_callback (prof, gc_finalized); + mono_native_tls_alloc (&debugger_tls_id, NULL); /* Needed by the hash_table_new_type () call below */ @@ -3373,6 +3381,32 @@ emit_type_load (gpointer key, gpointer value, gpointer user_data) process_profiler_event (EVENT_KIND_TYPE_LOAD, value); } + +static void gc_finalizing (MonoProfiler *prof) +{ + DebuggerTlsData *tls; + + if (is_debugger_thread ()) + return; + + tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); + g_assert (tls); + tls->gc_finalizing = TRUE; +} + +static void gc_finalized (MonoProfiler *prof) +{ + DebuggerTlsData *tls; + + if (is_debugger_thread ()) + return; + + tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id); + g_assert (tls); + tls->gc_finalizing = FALSE; +} + + static char* strdup_tolower (char *s) { @@ -6022,15 +6056,35 @@ clear_types_for_assembly (MonoAssembly *assembly) mono_loader_unlock (); } + +static void +count_thread_check_gc_finalizer (gpointer key, gpointer value, gpointer user_data) +{ + MonoThread *thread = (MonoThread *)value; + gboolean *ret = (gboolean *)user_data; + if (mono_gc_is_finalizer_internal_thread(thread->internal_thread)) { + DebuggerTlsData *tls = (DebuggerTlsData *)mono_g_hash_table_lookup (thread_to_tls, thread->internal_thread); + if (!tls->gc_finalizing) { //GC Finalizer is not running some finalizer code, so ignore it + *ret = TRUE; + return; + } + } +} + static void add_thread (gpointer key, gpointer value, gpointer user_data) { - MonoInternalThread *thread = (MonoInternalThread *)value; + MonoThread *thread = (MonoThread *)value; Buffer *buf = (Buffer *)user_data; - + if (mono_gc_is_finalizer_internal_thread(thread->internal_thread)) { + DebuggerTlsData *tls = (DebuggerTlsData *)mono_g_hash_table_lookup (thread_to_tls, thread->internal_thread); + if (!tls->gc_finalizing) //GC Finalizer is not running some finalizer code, so ignore it + return; + } buffer_add_objid (buf, (MonoObject*)thread); } + static ErrorCode do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 *p, guint8 **endp) { @@ -6588,9 +6642,15 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf) } case CMD_VM_ALL_THREADS: { // FIXME: Domains + gboolean remove_gc_finalizing; mono_loader_lock (); - buffer_add_int (buf, mono_g_hash_table_size (tid_to_thread_obj)); + int count = mono_g_hash_table_size (tid_to_thread_obj); + mono_g_hash_table_foreach (tid_to_thread_obj, count_thread_check_gc_finalizer, &remove_gc_finalizing); + if (remove_gc_finalizing) + count--; + buffer_add_int (buf, count); mono_g_hash_table_foreach (tid_to_thread_obj, add_thread, buf); + mono_loader_unlock (); break; } -- 2.7.4