1
0
Fork 0

Merge pull request #98964 from RandomShaper/fix_classdb_deadlock_4.3

[4.3] Fix deadlocks related to ClassDB queries about global classes
This commit is contained in:
Rémi Verschelde 2024-11-15 19:08:18 +01:00
commit 758a42196c
No known key found for this signature in database
GPG Key ID: C3336907360768E1
2 changed files with 56 additions and 35 deletions

View File

@ -664,58 +664,76 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
}
bool ClassDB::can_instantiate(const StringName &p_class) {
OBJTYPE_RLOCK;
String script_path;
{
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
}
script_path = ScriptServer::get_global_class_path(p_class);
goto use_script; // Open the lock for resource loading.
}
String path = ScriptServer::get_global_class_path(p_class);
Ref<Script> scr = ResourceLoader::load(path);
return scr.is_valid() && scr->is_valid() && !scr->is_abstract();
}
#ifdef TOOLS_ENABLED
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
return false;
}
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
return false;
}
#endif
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance));
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance));
}
use_script:
Ref<Script> scr = ResourceLoader::load(script_path);
return scr.is_valid() && scr->is_valid() && !scr->is_abstract();
}
bool ClassDB::is_abstract(const StringName &p_class) {
OBJTYPE_RLOCK;
String script_path;
{
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
}
script_path = ScriptServer::get_global_class_path(p_class);
goto use_script; // Open the lock for resource loading.
}
String path = ScriptServer::get_global_class_path(p_class);
Ref<Script> scr = ResourceLoader::load(path);
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
return ti->creation_func == nullptr && (!ti->gdextension || ti->gdextension->create_instance == nullptr);
}
return ti->creation_func == nullptr && (!ti->gdextension || ti->gdextension->create_instance == nullptr);
use_script:
Ref<Script> scr = ResourceLoader::load(script_path);
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
}
bool ClassDB::is_virtual(const StringName &p_class) {
OBJTYPE_RLOCK;
String script_path;
{
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
ClassInfo *ti = classes.getptr(p_class);
if (!ti) {
if (!ScriptServer::is_global_class(p_class)) {
ERR_FAIL_V_MSG(false, "Cannot get class '" + String(p_class) + "'.");
}
script_path = ScriptServer::get_global_class_path(p_class);
goto use_script; // Open the lock for resource loading.
}
String path = ScriptServer::get_global_class_path(p_class);
Ref<Script> scr = ResourceLoader::load(path);
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
}
#ifdef TOOLS_ENABLED
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
return false;
}
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
return false;
}
#endif
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual);
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual);
}
use_script:
Ref<Script> scr = ResourceLoader::load(script_path);
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
}
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {

View File

@ -511,6 +511,9 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimationNodeStateMachine);
GDREGISTER_CLASS(AnimationNodeStateMachinePlayback);
GDREGISTER_INTERNAL_CLASS(AnimationNodeStartState);
GDREGISTER_INTERNAL_CLASS(AnimationNodeEndState);
GDREGISTER_CLASS(AnimationNodeSync);
GDREGISTER_CLASS(AnimationNodeStateMachineTransition);
GDREGISTER_CLASS(AnimationNodeOutput);