Skip to content

Fix issue with GO crash#250

Merged
AGulev merged 4 commits intomainfrom
create-go-crash
Nov 18, 2025
Merged

Fix issue with GO crash#250
AGulev merged 4 commits intomainfrom
create-go-crash

Conversation

@AGulev
Copy link
Contributor

@AGulev AGulev commented Nov 17, 2025

Fix #246

@AGulev AGulev requested a review from britzl November 17, 2025 18:19
@AGulev
Copy link
Contributor Author

AGulev commented Nov 17, 2025

I can't say I'm 100% happy with the solution, but in case of swap (if I fix just capacity issue) I get crash I can't figure out how to fix. If I turn ASAN on, it doesn't happen, but crashes without ASAN all the time.
Current solutions solve the issue, but bones created only after new bones were removed.

  BUG IN CLIENT OF LIBMALLOC: memory corruption of free block
  Abort Cause 50031886080


  Thread 0 Crashed:: engine_main Dispatch queue: com.apple.main-thread
  0   libsystem_malloc.dylib                   0x190066b5c _xzm_xzone_malloc_freelist_outlined + 864
  1   libc++abi.dylib                          0x1901f9a78 operator new(unsigned long) + 52
  4   dmengine                                 0x101081430 dmGameObject::NewInstance(dmGameObject::CollectionHandle*, dmGameObject::Prototype*, char const*) +
8
  (gameobject.cpp:801) [inlined]
  5   dmengine                                 0x101081430 dmGameObject::New(dmGameObject::CollectionHandle*, char const*) + 96 (gameobject.cpp:958)
  (comp_spine_model.cpp:268)
  8   dmengine                                 0x10101fe44 dmSpine::SetupComponentFromScene(dmSpine::SpineModelWorld*, dmSpine::SpineModelComponent*,
  dmSpine::SpineSceneResource*, bool, bool) + 224 (comp_spine_model.cpp:447)
  9   dmengine                                 0x101021fa0 dmSpine::CompSpineModelSetProperty(dmGameObject::ComponentSetPropertyParams const&) + 580
  (comp_spine_model.cpp:1381)
  10  dmengine                                 0x10108787c dmGameObject::SetProperty(dmGameObject::Instance*, unsigned long long, unsigned long long,
  dmGameObject::PropertyOptions, dmGameObject::PropertyVar const&) + 676 (gameobject.cpp:3718)
  11  dmengine                                 0x10108db14 dmGameObject::Script_Set(lua_State*) + 644 (gameobject_script.cpp:819)
  12  dmengine                                 0x1011b39fc lj_BC_FUNCC + 44
  13  dmengine                                 0x1011cb640 lua_pcall + 148
  14  dmengine                                 0x101196964 dmScript::PCall(lua_State*, int, int) + 20 (script.cpp:1535) [inlined]
  15  dmengine                                 0x101196964 dmScript::InvokeCallback(dmScript::LuaCallbackInfo*, void (*)(lua_State*, void*), void*) + 208
  (script.cpp:2014)
  16  dmengine                                 0x1011a1958 dmScript::LuaTimerCallback(dmScript::TimerWorld*, dmScript::TimerEventType, unsigned int, float,
  unsigned long, unsigned long) + 92 (script_timer.cpp:530)
  17  dmengine                                 0x1011a062c dmScript::UpdateTimers(dmScript::TimerWorld*, float) + 248 (script_timer.cpp:253)
  18  dmengine                                 0x1011954c0 dmScript::UpdateScriptWorld(dmScript::ScriptWorld*, float) + 88 (script.cpp:1196)
  19  dmengine                                 0x10107cb08 dmGameObject::CompScriptUpdate(dmGameObject::ComponentsUpdateParams const&,
  dmGameObject::ComponentsUpdateResult&) + 40 (comp_script.cpp:257)
  20  dmengine                                 0x101085cd0 dmGameObject::Update(dmGameObject::Collection*, dmGameObject::UpdateContext const*) + 424
  (gameobject.cpp:2642) [inlined]
  21  dmengine                                 0x101085cd0 dmGameObject::Update(dmGameObject::CollectionHandle*, dmGameObject::UpdateContext const*) + 464
  (gameobject.cpp:2731)
  22  dmengine                                 0x1010b62f0 dmGameSystem::CompCollectionProxyUpdate(dmGameObject::ComponentsUpdateParams const&,
  dmGameObject::ComponentsUpdateResult&) + 448 (comp_collection_proxy.cpp:371)
  23  dmengine                                 0x101085cd0 dmGameObject::Update(dmGameObject::Collection*, dmGameObject::UpdateContext const*) + 424
  (gameobject.cpp:2642) [inlined]
  24  dmengine                                 0x101085cd0 dmGameObject::Update(dmGameObject::CollectionHandle*, dmGameObject::UpdateContext const*) + 464
  (gameobject.cpp:2731)
  25  dmengine                                 0x10102fc84 dmEngine::StepFrame(dmEngine::Engine*, float) + 876 (engine.cpp:1937) [inlined]
  26  dmengine                                 0x10102fc84 dmEngine::Step(dmEngine::Engine*) + 1160 (engine.cpp:2135)
  27  dmengine                                 0x101030354 dmEngineUpdate(dmEngine::Engine*) + 32 (engine.cpp:2496)
  28  dmengine                                 0x101031020 dmEngine::RunLoop(dmEngine::RunLoopParams const*) + 104 (engine_loop.cpp:83)
  29  dmengine                                 0x101030fa0 EngineMain(int, char**) + 80 (engine_main.cpp:55) [inlined]
  30  dmengine                                 0x101030fa0 engine_main(int, char**) + 104 (engine_main.cpp:151)
  31  dyld                                     0x18fe79d54 start + 7184

@AGulev AGulev requested a review from JCash November 18, 2025 08:05
return dmGameObject::UPDATE_RESULT_OK;
}

dmGameObject::UpdateResult CompSpineModelPostUpdate(const dmGameObject::ComponentsPostUpdateParams& params)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bones creation moved into PostUpdate - this is the main fix

-- bones don't exist immidiatly after model replace, because we have to wait to remove old bones
timer.delay(0, false, function()
update_debug_spine_bones(self, self.spine_a_url)
end)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main inconvenience here, you can't immediately use bones after scenes swap

component->m_BoneNameToNodeInstanceIndex.SetCapacity((skeleton->bonesCount+1)/2, skeleton->bonesCount);
if (component->m_BoneNameToNodeInstanceIndex.Capacity() < skeleton->bonesCount)
{
component->m_BoneNameToNodeInstanceIndex.SetCapacity((skeleton->bonesCount+1)/2, skeleton->bonesCount);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We nowadays have a new function dmHashTable::OffsetCapacity(grow) to make it easier to use, and keep a reasonable split between the table and bucket sizes.

@AGulev AGulev changed the base branch from editor-model-performance to main November 18, 2025 08:58
@AGulev AGulev merged commit 28cf957 into main Nov 18, 2025
27 checks passed
@AGulev AGulev deleted the create-go-crash branch November 18, 2025 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Changing the scene at runtime for a Spine Model with enabled Create Go Bones causes a crash

2 participants