summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2020-09-26 19:21:09 +0200
committerPedro J. Estébanez <pedrojrulez@gmail.com>2020-09-26 19:21:09 +0200
commitde4e54dd9150b0bc8bcb2ec643dd40eb4d3598d0 (patch)
tree2a9f4153bbe6de81c0603532b0212135e339ec28
parent84cec777c14f5d6bc3fbed425906211044429380 (diff)
Avoid infinite loop in GDScript at shutdown
-rw-r--r--modules/gdscript/gdscript.cpp14
1 files changed, 12 insertions, 2 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 7f303a966d..3519038ae6 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2039,8 +2039,15 @@ GDScriptLanguage::~GDScriptLanguage() {
}
// Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit).
- while (script_list.first()) {
- GDScript *script = script_list.first()->self();
+ SelfList<GDScript> *s = script_list.first();
+ while (s) {
+ GDScript *script = s->self();
+ // This ensures the current script is not released before we can check what's the next one
+ // in the list (we can't get the next upfront because we don't know if the reference breaking
+ // will cause it -or any other after it, for that matter- to be released so the next one
+ // is not the same as before).
+ script->reference();
+
for (Map<StringName, GDScriptFunction *>::Element *E = script->member_functions.front(); E; E = E->next()) {
GDScriptFunction *func = E->get();
for (int i = 0; i < func->argument_types.size(); i++) {
@@ -2051,6 +2058,9 @@ GDScriptLanguage::~GDScriptLanguage() {
for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) {
E->get().data_type.script_type_ref = Ref<Script>();
}
+
+ s = s->next();
+ script->unreference();
}
singleton = NULL;