diff options
| author | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2020-01-16 17:11:13 +0100 |
|---|---|---|
| committer | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2020-01-16 17:47:36 +0100 |
| commit | d68b9c20d69e037cff60260fe2e1fb198c62bba4 (patch) | |
| tree | 716143844fa350e35d46f595c6fabf3ee1b73313 /modules/mono/mono_gd/gd_mono_utils.cpp | |
| parent | f2d45676c949782febd59cdb25674d2058291a52 (diff) | |
| download | redot-engine-d68b9c20d69e037cff60260fe2e1fb198c62bba4.tar.gz | |
Mono/C#: Script interface calls now attach the current thread
Added guards to all C# script interface calls to attach the current thread
for the current scope if the thread is not already attached.
This is far from ideal, as attaching the thread is not cheap and all managed
thread local storage is lost when we detach the thread at the end of the calls.
However, it's the best we can do for now to avoid crashing
when an unattached thread tries to interact with C# code.
Diffstat (limited to 'modules/mono/mono_gd/gd_mono_utils.cpp')
| -rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.cpp | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 6bb9f28a32..4e7f590a69 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -125,10 +125,12 @@ void set_main_thread(MonoThread *p_thread) { mono_thread_set_main(p_thread); } -void attach_current_thread() { - ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); - MonoThread *mono_thread = mono_thread_attach(mono_get_root_domain()); - ERR_FAIL_NULL(mono_thread); +MonoThread *attach_current_thread() { + ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL); + MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain(); + MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain()); + ERR_FAIL_NULL_V(mono_thread, NULL); + return mono_thread; } void detach_current_thread() { @@ -138,10 +140,20 @@ void detach_current_thread() { mono_thread_detach(mono_thread); } +void detach_current_thread(MonoThread *p_mono_thread) { + ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized()); + ERR_FAIL_NULL(p_mono_thread); + mono_thread_detach(p_mono_thread); +} + MonoThread *get_current_thread() { return mono_thread_current(); } +bool is_thread_attached() { + return mono_domain_get() != NULL; +} + void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) { GDMonoMethod *ctor = p_class->get_method(".ctor", 0); ERR_FAIL_NULL(ctor); @@ -617,4 +629,19 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon } // namespace Marshal +ScopeThreadAttach::ScopeThreadAttach() : + mono_thread(NULL) { + if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) { + mono_thread = GDMonoUtils::attach_current_thread(); + } +} + +ScopeThreadAttach::~ScopeThreadAttach() { + if (unlikely(mono_thread)) { + GDMonoUtils::detach_current_thread(mono_thread); + } +} + +// namespace Marshal + } // namespace GDMonoUtils |
