From 37b6a36cc4b5a4dec6c2c2996864ca06c7f37672 Mon Sep 17 00:00:00 2001 From: Lyuma Date: Sun, 1 Nov 2020 00:44:15 -0700 Subject: [PATCH] Avoid reentrant OBJTYPE_RLOCK in ClassDB Fixes #43020 when a thread uses ClassDB while main thread calls is_parent_class(). --- core/class_db.cpp | 26 +++++++++++++++++--------- core/class_db.h | 5 +++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/core/class_db.cpp b/core/class_db.cpp index ad85cd0d623..81bc9015618 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -242,21 +242,25 @@ HashMap ClassDB::classes; HashMap ClassDB::resource_base_extensions; HashMap ClassDB::compat_classes; -bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { - OBJTYPE_RLOCK; - +bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_inherits) { StringName inherits = p_class; while (inherits.operator String().length()) { if (inherits == p_inherits) { return true; } - inherits = get_parent_class(inherits); + inherits = _get_parent_class(inherits); } return false; } +bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { + OBJTYPE_RLOCK; + + return _is_parent_class(p_class, p_inherits); +} + void ClassDB::get_class_list(List *p_classes) { OBJTYPE_RLOCK; @@ -275,7 +279,7 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, Listpush_back(*k); } } @@ -287,7 +291,7 @@ void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, Listpush_back(*k); } } @@ -315,14 +319,18 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) return p_class; } -StringName ClassDB::get_parent_class(const StringName &p_class) { - OBJTYPE_RLOCK; - +StringName ClassDB::_get_parent_class(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); ERR_FAIL_COND_V_MSG(!ti, StringName(), "Cannot get class '" + String(p_class) + "'."); return ti->inherits; } +StringName ClassDB::get_parent_class(const StringName &p_class) { + OBJTYPE_RLOCK; + + return _get_parent_class(p_class); +} + ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { OBJTYPE_RLOCK; diff --git a/core/class_db.h b/core/class_db.h index 4734b06c7a6..22072066d93 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -164,6 +164,11 @@ public: static HashMap> default_values; static Set default_values_cached; +private: + // Non-locking variants of get_parent_class and is_parent_class. + static StringName _get_parent_class(const StringName &p_class); + static bool _is_parent_class(const StringName &p_class, const StringName &p_inherits); + public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! template