Garbage collector deadlock when initialising new nodes after using temp data resource

I was getting a consistent garbage collector deadlock at the exact same point in my code using V4.2.1. I believe I fixed it, but I can’t reproduce it in an MRP. I am leaving this post for anyone who may have an idea or if it occurs again.

Steps:

  1. I ran the program
  2. The program would load data from a data file into a temp data resource
  3. This temp data resource is passed to the data store singleton and sets appropriate values, then it is no longer used
  4. I then press a button to load nodes
  5. This loads different data from a data file and loads nodes into the scene based on the data
  6. While loading these nodes it regularly collided. The GC was freeing up memory from the temp resource while loading the nodes into the scene.

I looked at the nodes being loaded and I narrowed it down to two button variants. I reduced those down to no internal code and it would still occur, but if I didn’t add the empty button variants to the scene it appeared to stop.

I couldn’t see how empty variants could be the cause, so instead I looked at the data the GC was attempting to clear. I changed the temp data resource to just a class rather than a partial godot.reource class and it doesn’t appear to be happening anymore.

Main Thread
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_internal_new_csharp_script(Godot.NativeInterop.godot_ref* r_dest) Line 162 (Godot.NativeInterop.NativeFuncs.generated.cs:162)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.CreateScriptBridgeForType(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript) Line 515 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:515)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.GetOrLoadOrCreateScriptForType.__GetPathOtherwiseGetOrCreateScript|19_0(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript, out string scriptPath) Line 490 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:490)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.GetOrLoadOrCreateScriptForType(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript) Line 496 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:496)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.UpdateScriptClassInfo(nint scriptPtr, Godot.NativeInterop.godot_string* outClassName, Godot.NativeInterop.godot_bool* outTool, Godot.NativeInterop.godot_bool* outGlobal, Godot.NativeInterop.godot_bool* outAbstract, Godot.NativeInterop.godot_string* outIconPath, Godot.NativeInterop.godot_array* outMethodsDest, Godot.NativeInterop.godot_dictionary* outRpcFunctionsDest, Godot.NativeInterop.godot_dictionary* outEventSignalsDest, Godot.NativeInterop.godot_ref* outBaseScript) Line 793 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:793)
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_internal_reload_registered_script(nint scriptPtr) Line 175 (Godot.NativeInterop.NativeFuncs.generated.cs:175)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.CreateScriptBridgeForType(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript) Line 521 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:521)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.GetOrCreateScriptBridgeForType(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript) Line 466 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:466)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.GetOrCreateScriptBridgeForPath(Godot.NativeInterop.godot_string* scriptPath, Godot.NativeInterop.godot_ref* outScript) Line 451 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:451)
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_internal_script_load(Godot.NativeInterop.godot_string p_path, Godot.NativeInterop.godot_ref* r_dest) Line 169 (Godot.NativeInterop.NativeFuncs.generated.cs:169)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.GetOrLoadOrCreateScriptForType(System.Type scriptType, Godot.NativeInterop.godot_ref* outScript) Line 502 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:502)
GodotSharp.dll!Godot.NativeInterop.InteropUtils.TieManagedToUnmanaged(Godot.GodotObject managed, nint unmanaged, Godot.StringName nativeName, bool refCounted, System.Type type, System.Type nativeType) Line 70 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\NativeInterop\InteropUtils.cs:70)
GodotSharp.dll!Godot.GodotObject._ConstructAndInitialize(delegate* unmanaged nativeCtor, Godot.StringName nativeName, System.Type cachedType, bool refCounted) Line 40 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\GodotObject.base.cs:40)
GodotSharp.dll!Godot.Resource.Resource() Line 75 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Resource.cs:75)
Tapestry!Tapestry.GraphNodes.Sections.Elements.NodeSectionElement<Godot.TextEdit, string>.NodeSectionElement() Line 51 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\sections\elements\NodeSectionElement.cs:51)
Tapestry!Tapestry.GraphNodes.Sections.Elements.TextEdit.TextEdit(string text, string placeholder, Godot.Vector2 minSize) Line 15 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\sections\elements\TextEdit.cs:15)
Tapestry!Tapestry.GraphNodes.Templates.Sections.TextEdit._GetSection() Line 53 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\templates\sections\TextEdit.cs:53)
Tapestry!Tapestry.GraphNodes.Templates.Sections.Section.Render(Tapestry.GraphNodes.TapestryNode parent, int index) Line 43 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\templates\sections\Section.cs:43)
Tapestry!Tapestry.GraphNodes.Templates.Template._Render() Line 142 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\templates\Template.cs:142)
Tapestry!Tapestry.GraphNodes.Templates.Template.Render(Tapestry.GraphNodes.TapestryNode parent) Line 132 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\templates\Template.cs:132)
Tapestry!Tapestry.GraphNodes.TapestryNode._Ready() Line 115 (\godotproject\Tapestry\addons\tapestry\components\graphNodes\TapestryNode.cs:115)
GodotSharp.dll!Godot.Node.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 2117 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Node.cs:2117)
GodotSharp.dll!Godot.CanvasItem.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 1370 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\CanvasItem.cs:1370)
GodotSharp.dll!Godot.Control.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 2841 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Control.cs:2841)
GodotSharp.dll!Godot.Container.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 136 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Container.cs:136)
GodotSharp.dll!Godot.GraphElement.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 312 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\GraphElement.cs:312)
GodotSharp.dll!Godot.GraphNode.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 428 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\GraphNode.cs:428)
Tapestry!Tapestry.GraphNodes.TapestryNode.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 436 (Tapestry.GraphNodes.TapestryNode_ScriptMethods.generated.cs:436)
Tapestry!Tapestry.GraphNodes.SpeechNode.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 60 (Tapestry.GraphNodes.SpeechNode_ScriptMethods.generated.cs:60)
Tapestry!Tapestry.GraphNodes.PlayerSpeechNode.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name method, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 40 (Tapestry.GraphNodes.PlayerSpeechNode_ScriptMethods.generated.cs:40)
GodotSharp.dll!Godot.Bridge.CSharpInstanceBridge.Call(nint godotObjectGCHandle, Godot.NativeInterop.godot_string_name* method, Godot.NativeInterop.godot_variant** args, int argCount, Godot.NativeInterop.godot_variant_call_error* refCallError, Godot.NativeInterop.godot_variant* ret) Line 24 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\CSharpInstanceBridge.cs:24)
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_method_bind_ptrcall(nint p_method_bind, nint p_instance, void** p_args, void* p_ret) Line 353 (Godot.NativeInterop.NativeFuncs.generated.cs:353)
GodotSharp.dll!Godot.NativeCalls.godot_icall_3_690(nint method, nint ptr, nint arg1, Godot.NativeInterop.godot_bool arg2, int arg3) Line 6156 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\NativeCalls.cs:6156)
GodotSharp.dll!Godot.Node.AddChild(Godot.Node node, bool forceReadableName, Godot.Node.InternalMode internal) Line 688 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Node.cs:688)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit._AddNode(Tapestry.GraphNodes.TapestryNode node) Line 280 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:280)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit.AddNode(string name, Godot.Collections.Dictionary<string, Godot.Variant> data) Line 262 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:262)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit._SetNodes(Godot.Collections.Dictionary<string, Godot.Collections.Dictionary<string, Godot.Variant>> nodes) Line 256 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:256)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit._SetData(Godot.Collections.Dictionary<string, Godot.Variant> data) Line 218 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:218)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit.SetData(Godot.Collections.Dictionary<string, Godot.Variant> data) Line 205 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:205)
Tapestry!Tapestry.GraphEdit.TapestryGraphEdit.LoadData() Line 147 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\TapestryGraphEdit.cs:147)
Tapestry!Tapestry.GraphEdit.UI.GraphTab.Open() Line 63 (\godotproject\Tapestry\addons\tapestry\components\graphEdit\ui\tabs\GraphTab.cs:63)
Tapestry!Tapestry.UI.TapestryUI.OpenGraphTab(Tapestry.GraphEdit.UI.GraphTab graphTab) Line 123 (\godotproject\Tapestry\addons\tapestry\components\ui\TapestryUI.cs:123)
Tapestry!Tapestry.UI.Controller._OpenGraphTab(Tapestry.GraphEdit.UI.GraphTab graphTab) Line 97 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:97)
Tapestry!Tapestry.UI.Controller._OpenGraphTab(int index) Line 102 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:102)
Tapestry!Tapestry.UI.Controller._OnGraphOpened(object sender, Tapestry.GraphEdit.UI.GraphOpenedEventArgs eventArgs) Line 132 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:132)
Tapestry!Tapestry.UI.TapestryUI._InitGraphTabs.AnonymousMethod__43_0(long index) Line 254 (\godotproject\Tapestry\addons\tapestry\components\ui\TapestryUI.cs:254)
GodotSharp.dll!Godot.TabContainer.TabChangedTrampoline(object delegateObj, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 596 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\TabContainer.cs:596)
GodotSharp.dll!Godot.DelegateUtils.InvokeWithVariantArgs(nint delegateGCHandle, void* trampoline, Godot.NativeInterop.godot_variant** args, int argc, Godot.NativeInterop.godot_variant* outRet) Line 62 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\DelegateUtils.cs:62)
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_method_bind_ptrcall(nint p_method_bind, nint p_instance, void** p_args, void* p_ret) Line 353 (Godot.NativeInterop.NativeFuncs.generated.cs:353)
GodotSharp.dll!Godot.NativeCalls.godot_icall_3_690(nint method, nint ptr, nint arg1, Godot.NativeInterop.godot_bool arg2, int arg3) Line 6156 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\NativeCalls.cs:6156)
GodotSharp.dll!Godot.Node.AddChild(Godot.Node node, bool forceReadableName, Godot.Node.InternalMode internal) Line 688 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Generated\GodotObjects\Node.cs:688)
Tapestry!Tapestry.UI.TapestryUI.AddNewGraphTab(Tapestry.GraphEdit.UI.GraphTab graphTab) Line 138 (\godotproject\Tapestry\addons\tapestry\components\ui\TapestryUI.cs:138)
Tapestry!Tapestry.UI.Controller._OpenNewGraphTab(Tapestry.Dialogues.Info.DialogueInfo dialogueInfo) Line 125 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:125)
Tapestry!Tapestry.UI.Controller._OpenGraphTab(Tapestry.Dialogues.Info.DialogueInfo dialogueInfo) Line 120 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:120)
Tapestry!Tapestry.UI.Controller.OpenGraph(Tapestry.Dialogues.Info.DialogueInfo dialogueInfo, string nodeName) Line 48 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:48)
Tapestry!Tapestry.UI.Controller.OpenGraph(object sender, Tapestry.GraphEdit.UI.OpenGraphEventArgs eventArgs) Line 42 (\godotproject\Tapestry\addons\tapestry\components\ui\Controller.cs:42)
Tapestry!Tapestry.UI.TapestryUI._OnOpenGraph(object sender, Tapestry.GraphEdit.UI.OpenGraphEventArgs eventArgs) Line 293 (\godotproject\Tapestry\addons\tapestry\components\ui\TapestryUI.cs:293)
Tapestry!Tapestry.Characters.UI.CharactersTab._OnOpenGraph(Tapestry.Characters.Character character) Line 98 (\godotproject\Tapestry\addons\tapestry\components\characters\ui\tabs\CharactersTab.cs:98)
Tapestry!Tapestry.Characters.UI.CharactersTab.AddCharacterToList.AnonymousMethod__0() Line 89 (\godotproject\Tapestry\addons\tapestry\components\characters\ui\tabs\CharactersTab.cs:89)
GodotSharp.dll!Godot.Callable.From.__Trampoline|1_0(object delegateObj, Godot.NativeInterop.NativeVariantPtrArgs args, out Godot.NativeInterop.godot_variant ret) Line 39 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Callable.generics.cs:39)
GodotSharp.dll!Godot.DelegateUtils.InvokeWithVariantArgs(nint delegateGCHandle, void* trampoline, Godot.NativeInterop.godot_variant** args, int argc, Godot.NativeInterop.godot_variant* outRet) Line 62 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\DelegateUtils.cs:62)
[External Code] (Unknown Source:0)

GC Thread
[Waiting on lock owned by Thread 30280] (Unknown Source:0)
GodotSharp.dll!Godot.Bridge.ScriptManagerBridge.RemoveScriptBridge(nint scriptPtr) Line 529 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\Bridge\ScriptManagerBridge.cs:529)
[External Code] (Unknown Source:0)
GodotSharp.dll!Godot.NativeInterop.NativeFuncs.godotsharp_internal_refcounted_disposed(nint ptr, nint gcHandleToFree, Godot.NativeInterop.godot_bool isFinalizer) Line 109 (Godot.NativeInterop.NativeFuncs.generated.cs:109)
GodotSharp.dll!Godot.GodotObject.Dispose(bool disposing) Line 117 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\GodotObject.base.cs:117)
GodotSharp.dll!Godot.GodotObject.~GodotObject() Line 80 (\root\godot\modules\mono\glue\GodotSharp\GodotSharp\Core\GodotObject.base.cs:80)
[External Code] (Unknown Source:0)