summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnacio Roldán Etcheverry <neikeq@users.noreply.github.com>2019-07-25 00:24:35 +0200
committerGitHub <noreply@github.com>2019-07-25 00:24:35 +0200
commitad0d87b4dddfe6b9e88510dd526bcd4028ba3030 (patch)
treefdda042e7c5c3c0aa551d884bc019008b18a7fed
parentadae2b073811d0f81afdfab277fdb27d2ba9f16a (diff)
parentc0cdbb793822961e68727925d0f3f4e00f780306 (diff)
Merge pull request #30802 from neikeq/exc-policy-and-issue-30519
Unhandled exception policy and fix external editors on Windows
-rw-r--r--modules/mono/csharp_script.cpp1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs11
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs22
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs5
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp14
-rw-r--r--modules/mono/mono_gd/gd_mono.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp15
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp17
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
10 files changed, 78 insertions, 24 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 078a490b22..846c84d222 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -629,7 +629,6 @@ void CSharpLanguage::frame() {
if (exc) {
GDMonoUtils::debug_unhandled_exception(exc);
- GD_UNREACHABLE();
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 90dec43412..9b5afb94a3 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -298,7 +298,16 @@ namespace GodotTools
if (line >= 0)
scriptPath += $";{line + 1};{col}";
- GetMonoDevelopInstance(GodotSharpDirs.ProjectSlnPath).Execute(scriptPath);
+ try
+ {
+ GetMonoDevelopInstance(GodotSharpDirs.ProjectSlnPath).Execute(scriptPath);
+ }
+ catch (FileNotFoundException)
+ {
+ string editorName = editor == ExternalEditor.VisualStudioForMac ? "Visual Studio" : "MonoDevelop";
+ GD.PushError($"Cannot find code editor: {editorName}");
+ return Error.FileNotFound;
+ }
break;
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs b/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
index 0c8d86e799..61a0a992ce 100644
--- a/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using GodotTools.Internals;
+using GodotTools.Utils;
namespace GodotTools
{
@@ -30,7 +31,7 @@ namespace GodotTools
if (Utils.OS.IsOSX())
{
- string bundleId = CodeEditorBundleIds[editorId];
+ string bundleId = BundleIds[editorId];
if (Internal.IsOsxAppBundleInstalled(bundleId))
{
@@ -47,12 +48,12 @@ namespace GodotTools
}
else
{
- command = CodeEditorPaths[editorId];
+ command = OS.PathWhich(ExecutableNames[editorId]);
}
}
else
{
- command = CodeEditorPaths[editorId];
+ command = OS.PathWhich(ExecutableNames[editorId]);
}
args.Add("--ipc-tcp");
@@ -70,6 +71,9 @@ namespace GodotTools
args.Add("\"" + Path.GetFullPath(filePath.NormalizePath()) + cursor + "\"");
}
+ if (command == null)
+ throw new FileNotFoundException();
+
if (newWindow)
{
process = Process.Start(new ProcessStartInfo
@@ -99,20 +103,20 @@ namespace GodotTools
this.editorId = editorId;
}
- private static readonly IReadOnlyDictionary<EditorId, string> CodeEditorPaths;
- private static readonly IReadOnlyDictionary<EditorId, string> CodeEditorBundleIds;
+ private static readonly IReadOnlyDictionary<EditorId, string> ExecutableNames;
+ private static readonly IReadOnlyDictionary<EditorId, string> BundleIds;
static MonoDevelopInstance()
{
if (Utils.OS.IsOSX())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// Rely on PATH
{EditorId.MonoDevelop, "monodevelop"},
{EditorId.VisualStudioForMac, "VisualStudio"}
};
- CodeEditorBundleIds = new Dictionary<EditorId, string>
+ BundleIds = new Dictionary<EditorId, string>
{
// TODO EditorId.MonoDevelop
{EditorId.VisualStudioForMac, "com.microsoft.visual-studio"}
@@ -120,7 +124,7 @@ namespace GodotTools
}
else if (Utils.OS.IsWindows())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// XamarinStudio is no longer a thing, and the latest version is quite old
// MonoDevelop is available from source only on Windows. The recommendation
@@ -131,7 +135,7 @@ namespace GodotTools
}
else if (Utils.OS.IsUnix())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// Rely on PATH
{EditorId.MonoDevelop, "monodevelop"}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
index 3ae6c10bbf..288c65de74 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
@@ -10,8 +10,9 @@ namespace GodotTools.Utils
{
foreach (T elem in enumerable)
{
- if (predicate(elem) != null)
- return elem;
+ T result = predicate(elem);
+ if (result != null)
+ return result;
}
return orElse;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 571bf598f3..8b9813f472 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -283,6 +283,18 @@ void GDMono::initialize() {
add_mono_shared_libs_dir_to_path();
+ {
+ PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/unhandled_exception_policy", PROPERTY_HINT_ENUM,
+ vformat("Terminate Application:%s,Log Error:%s", (int)POLICY_TERMINATE_APP, (int)POLICY_LOG_ERROR));
+ unhandled_exception_policy = (UnhandledExceptionPolicy)(int)GLOBAL_DEF(exc_policy_prop.name, (int)POLICY_TERMINATE_APP);
+ ProjectSettings::get_singleton()->set_custom_property_info(exc_policy_prop.name, exc_policy_prop);
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // Unhandled exceptions should not terminate the editor
+ unhandled_exception_policy = POLICY_LOG_ERROR;
+ }
+ }
+
GDMonoAssembly::initialize();
gdmono_profiler_init();
@@ -1063,6 +1075,8 @@ GDMono::GDMono() {
#ifdef TOOLS_ENABLED
api_editor_hash = 0;
#endif
+
+ unhandled_exception_policy = POLICY_TERMINATE_APP;
}
GDMono::~GDMono() {
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index deebe5fd50..c5bcce4fa1 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -80,6 +80,13 @@ String to_string(Type p_type);
class GDMono {
+public:
+ enum UnhandledExceptionPolicy {
+ POLICY_TERMINATE_APP,
+ POLICY_LOG_ERROR
+ };
+
+private:
bool runtime_initialized;
bool finalizing_scripts_domain;
@@ -102,6 +109,8 @@ class GDMono {
HashMap<uint32_t, HashMap<String, GDMonoAssembly *> > assemblies;
+ UnhandledExceptionPolicy unhandled_exception_policy;
+
void _domain_assemblies_cleanup(uint32_t p_domain_id);
bool _are_api_assemblies_out_of_sync();
@@ -162,7 +171,9 @@ public:
static GDMono *get_singleton() { return singleton; }
- static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data);
+ GD_NORETURN static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data);
+
+ UnhandledExceptionPolicy get_unhandled_exception_policy() const { return unhandled_exception_policy; }
// Do not use these, unless you know what you're doing
void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly);
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index a84332d4cd..e50e3b0794 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -108,9 +108,18 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) {
mono_unhandled_exception((MonoObject *)p_exc); // prints the exception as well
- // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
- GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
- GD_UNREACHABLE();
+
+ if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) {
+ // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
+ GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
+ GD_UNREACHABLE();
+ } else {
+#ifdef DEBUG_ENABLED
+ GDMonoUtils::debug_send_unhandled_exception_error((MonoException *)p_exc);
+ if (ScriptDebugger::get_singleton())
+ ScriptDebugger::get_singleton()->idle_poll();
+#endif
+ }
}
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 2d77bde27c..0d82723913 100644
--- a/modules/mono/mono_gd/gd_mono_internals.h
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -45,7 +45,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
* Do not call this function directly.
* Use GDMonoUtils::debug_unhandled_exception(MonoException *) instead.
*/
-GD_NORETURN void unhandled_exception(MonoException *p_exc);
+void unhandled_exception(MonoException *p_exc);
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 5987fa8ebb..7afdfc8ac8 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -37,6 +37,10 @@
#include "core/project_settings.h"
#include "core/reference.h"
+#ifdef TOOLS_ENABLED
+#include "editor/script_editor_debugger.h"
+#endif
+
#include "../csharp_script.h"
#include "../utils/macros.h"
#include "../utils/mutex_utils.h"
@@ -596,8 +600,14 @@ void debug_print_unhandled_exception(MonoException *p_exc) {
void debug_send_unhandled_exception_error(MonoException *p_exc) {
#ifdef DEBUG_ENABLED
- if (!ScriptDebugger::get_singleton())
+ if (!ScriptDebugger::get_singleton()) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ ERR_PRINTS(GDMonoUtils::get_exception_name_and_message(p_exc));
+ }
+#endif
return;
+ }
_TLS_RECURSION_GUARD_;
@@ -621,7 +631,7 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) {
if (unexpected_exc) {
GDMonoInternals::unhandled_exception(unexpected_exc);
- GD_UNREACHABLE();
+ return;
}
Vector<ScriptLanguage::StackInfo> _si;
@@ -655,7 +665,6 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) {
void debug_unhandled_exception(MonoException *p_exc) {
GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
- GD_UNREACHABLE();
}
void print_unhandled_exception(MonoException *p_exc) {
@@ -665,11 +674,9 @@ void print_unhandled_exception(MonoException *p_exc) {
void set_pending_exception(MonoException *p_exc) {
#ifdef NO_PENDING_EXCEPTIONS
debug_unhandled_exception(p_exc);
- GD_UNREACHABLE();
#else
if (get_runtime_invoke_count() == 0) {
debug_unhandled_exception(p_exc);
- GD_UNREACHABLE();
}
if (!mono_runtime_set_pending_exception(p_exc, false)) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index f535fbb6d0..d73743bf0b 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -289,7 +289,7 @@ void set_exception_message(MonoException *p_exc, String message);
void debug_print_unhandled_exception(MonoException *p_exc);
void debug_send_unhandled_exception_error(MonoException *p_exc);
-GD_NORETURN void debug_unhandled_exception(MonoException *p_exc);
+void debug_unhandled_exception(MonoException *p_exc);
void print_unhandled_exception(MonoException *p_exc);
/**