diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 8f8116e26ed..7df2043a62a 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -449,7 +449,7 @@ Vector CSharpLanguage::debug_get_current_stack_info() // Printing an error here will result in endless recursion, so we must be careful - if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_api_assembly()) + if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_api_assembly() || !GDMonoUtils::mono_cache.corlib_cache_updated) return Vector(); MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr()); @@ -503,6 +503,10 @@ Vector CSharpLanguage::stack_trace_get_info(MonoObjec return Vector(); } + // TODO + // what if the StackFrame method is null (method_decl is empty). should we skip this frame? + // can reproduce with a MissingMethodException on internal calls + sif.file = GDMonoMarshal::mono_string_to_godot(file_name); sif.line = file_line_num; sif.func = GDMonoMarshal::mono_string_to_godot(method_decl); diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp index 0b0b36e1e3f..48a285561d8 100644 --- a/modules/mono/editor/monodevelop_instance.cpp +++ b/modules/mono/editor/monodevelop_instance.cpp @@ -35,6 +35,8 @@ void MonoDevelopInstance::execute(const Vector &p_files) { + _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN) + ERR_FAIL_NULL(execute_method); ERR_FAIL_COND(gc_handle.is_null()); diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs index ced78f658d0..42ca57fbf98 100644 --- a/modules/mono/glue/cs_files/DebuggingUtils.cs +++ b/modules/mono/glue/cs_files/DebuggingUtils.cs @@ -26,6 +26,12 @@ namespace Godot MethodBase methodBase = frame.GetMethod(); + if (methodBase == null) + { + methodDecl = string.Empty; + return; + } + StringBuilder sb = new StringBuilder(); if (methodBase is MethodInfo methodInfo) diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index d02c73978e2..835a4614c12 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -44,10 +44,13 @@ namespace GDMonoUtils { MonoCache mono_cache; -#define CACHE_AND_CHECK(m_var, m_val) \ - { \ - m_var = m_val; \ - if (!m_var) ERR_PRINT("Mono Cache: Member " #m_var " is null. This is really bad!"); \ +#define CACHE_AND_CHECK(m_var, m_val) \ + { \ + m_var = m_val; \ + if (!m_var) { \ + ERR_EXPLAIN("Mono Cache: Member " #m_var " is null"); \ + ERR_FAIL(); \ + } \ } #define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val) @@ -133,6 +136,12 @@ void MonoCache::clear_members() { task_scheduler_handle = Ref(); } +void MonoCache::cleanup() { + + corlib_cache_updated = false; + godot_api_cache_updated = false; +} + #define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class)) void update_corlib_cache() { @@ -158,6 +167,8 @@ void update_corlib_cache() { CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true)); CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true)); #endif + + mono_cache.corlib_cache_updated = true; } void update_godot_api_cache() { @@ -231,6 +242,8 @@ void update_godot_api_cache() { MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr()); mono_runtime_object_init(task_scheduler); mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler); + + mono_cache.corlib_cache_updated = true; } void clear_cache() { @@ -402,6 +415,9 @@ void print_unhandled_exception(MonoObject *p_exc) { void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) { mono_print_unhandled_exception(p_exc); #ifdef DEBUG_ENABLED + if (!ScriptDebugger::get_singleton()) + return; + GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 597397ecedc..26664331702 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -129,10 +129,16 @@ struct MonoCache { Ref task_scheduler_handle; + bool corlib_cache_updated; + bool godot_api_cache_updated; + void clear_members(); - void cleanup() {} + void cleanup(); MonoCache() { + corlib_cache_updated = false; + godot_api_cache_updated = false; + clear_members(); } };