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

C#: Fix some crashes during assemblies reloading

This commit is contained in:
Ignacio Etcheverry
2019-07-08 15:18:38 +02:00
parent aa3b8f7dbb
commit dd22cc7527
2 changed files with 42 additions and 33 deletions

View File

@@ -867,6 +867,11 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
script->reload(p_soft_reload); script->reload(p_soft_reload);
script->update_exports(); script->update_exports();
if (!script->valid) {
script->pending_reload_instances.clear();
continue;
}
} else { } else {
const StringName &class_namespace = script->tied_class_namespace_for_reload; const StringName &class_namespace = script->tied_class_namespace_for_reload;
const StringName &class_name = script->tied_class_name_for_reload; const StringName &class_name = script->tied_class_name_for_reload;
@@ -897,12 +902,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
GDMonoClass *native = GDMonoUtils::get_class_native_base(script_class); GDMonoClass *native = GDMonoUtils::get_class_native_base(script_class);
Ref<CSharpScript> new_script = CSharpScript::create_for_managed_type(script_class, native); CSharpScript::initialize_for_managed_type(script, script_class, native);
CRASH_COND(new_script.is_null());
new_script->pending_reload_instances = script->pending_reload_instances;
new_script->pending_reload_state = script->pending_reload_state;
script = new_script;
} }
String native_name = NATIVE_GDMONOCLASS_NAME(script->native); String native_name = NATIVE_GDMONOCLASS_NAME(script->native);
@@ -953,7 +953,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
CRASH_COND(si != NULL); CRASH_COND(si != NULL);
#endif #endif
// Re-create script instance // Re-create script instance
obj->set_script(script.get_ref_ptr()); // will create the script instance as well obj->set_script(script.get_ref_ptr()); // will create the script instance as well
} }
} }
@@ -2673,35 +2672,46 @@ void CSharpScript::_bind_methods() {
Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) { Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native) {
// This method should not fail // This method should not fail, only assertions allowed
CRASH_COND(p_class == NULL); CRASH_COND(p_class == NULL);
// TODO OPTIMIZE: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time // TODO OPTIMIZE: Cache the 'CSharpScript' associated with this 'p_class' instead of allocating a new one every time
Ref<CSharpScript> script = memnew(CSharpScript); Ref<CSharpScript> script = memnew(CSharpScript);
script->name = p_class->get_name(); initialize_for_managed_type(script, p_class, p_native);
script->script_class = p_class;
script->native = p_native;
CRASH_COND(script->native == NULL); return script;
}
GDMonoClass *base = script->script_class->get_parent_class(); void CSharpScript::initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native) {
if (base != script->native) // This method should not fail, only assertions allowed
script->base = base;
script->valid = true; CRASH_COND(p_class == NULL);
script->tool = script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
if (!script->tool) { p_script->name = p_class->get_name();
GDMonoClass *nesting_class = script->script_class->get_nesting_class(); p_script->script_class = p_class;
script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute)); p_script->native = p_native;
CRASH_COND(p_script->native == NULL);
GDMonoClass *base = p_script->script_class->get_parent_class();
if (base != p_script->native)
p_script->base = base;
p_script->valid = true;
p_script->tool = p_script->script_class->has_attribute(CACHED_CLASS(ToolAttribute));
if (!p_script->tool) {
GDMonoClass *nesting_class = p_script->script_class->get_nesting_class();
p_script->tool = nesting_class && nesting_class->has_attribute(CACHED_CLASS(ToolAttribute));
} }
#if TOOLS_ENABLED #if TOOLS_ENABLED
if (!script->tool) { if (!p_script->tool) {
script->tool = script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly(); p_script->tool = p_script->script_class->get_assembly() == GDMono::get_singleton()->get_tools_assembly();
} }
#endif #endif
@@ -2710,10 +2720,10 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
// Native base methods must be fetched before the current class. // Native base methods must be fetched before the current class.
// Not needed if the script class itself is a native class. // Not needed if the script class itself is a native class.
if (script->script_class != script->native) { if (p_script->script_class != p_script->native) {
GDMonoClass *native_top = script->native; GDMonoClass *native_top = p_script->native;
while (native_top) { while (native_top) {
native_top->fetch_methods_with_godot_api_checks(script->native); native_top->fetch_methods_with_godot_api_checks(p_script->native);
if (native_top == CACHED_CLASS(GodotObject)) if (native_top == CACHED_CLASS(GodotObject))
break; break;
@@ -2723,19 +2733,17 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class, GD
} }
#endif #endif
script->script_class->fetch_methods_with_godot_api_checks(script->native); p_script->script_class->fetch_methods_with_godot_api_checks(p_script->native);
// Need to fetch method from base classes as well // Need to fetch method from base classes as well
GDMonoClass *top = script->script_class; GDMonoClass *top = p_script->script_class;
while (top && top != script->native) { while (top && top != p_script->native) {
top->fetch_methods_with_godot_api_checks(script->native); top->fetch_methods_with_godot_api_checks(p_script->native);
top = top->get_parent_class(); top = top->get_parent_class();
} }
script->load_script_signals(script->script_class, script->native); p_script->load_script_signals(p_script->script_class, p_script->native);
script->_update_member_info_no_exports(); p_script->_update_member_info_no_exports();
return script;
} }
bool CSharpScript::can_instance() const { bool CSharpScript::can_instance() const {

View File

@@ -144,6 +144,7 @@ class CSharpScript : public Script {
// Do not use unless you know what you are doing // Do not use unless you know what you are doing
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *); friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native); static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
protected: protected:
static void _bind_methods(); static void _bind_methods();