1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-05 12:10:55 +00:00

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.
This commit is contained in:
Ignacio Etcheverry
2020-01-16 17:11:13 +01:00
parent f2d45676c9
commit d68b9c20d6
3 changed files with 128 additions and 42 deletions

View File

@@ -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