Reentrancy in RecreateRenderState_Concurrent on UInstancedStaticMeshComponent during mesh compilation

Hi there,

We are experiencing a crash in `UActorComponent::RecreateRenderState_Concurrent()` which is re-entering itself (thus failing a `check(bRenderStateRecreating == false)`). This appears to be happening on a UInstancedStaticMeshComponent that is still compiling.

From the call stack, it is somewhat easy to see how this is possible (create render state -> update bounds -> cache navigation bounds -> get nav collision -> flush compilation -> create render state), but I have not been able to reproduce it in a stripped-down test project or a newer version of the engine.

Any guidance would be much appreciated. For more context, this appears to happen mostly with a cold-ish DDC in the editor. Once I run through things in PIE a few times, it seems to become less likely to happen.

Many regards,

Logan Smith

[Attachment Removed]

I attached the call stack to the original question, but just in case it’s useful to have it out in the open too, it looks like this:

UActorComponent::RecreateRenderState_Concurrent() ActorComponent.cpp:1831
FStaticMeshCompilingManager::PostCompilation(UStaticMesh *) StaticMeshCompiler.cpp:305
`FStaticMeshCompilingManager::FinishCompilation'::`22'::<lambda_2>::operator()(AsyncCompilationHelpers::ICompilable *) StaticMeshCompiler.cpp:414
[Inlined] UE::Core::Private::Function::TFunctionRefBase::operator()(AsyncCompilationHelpers::ICompilable *) Function.h:555
AsyncCompilationHelpers::FinishCompilation(TFunctionRef<…>, int, const FText &, const FLogCategoryBase &, TFunctionRef<…>) AsyncCompilationHelpers.cpp:162
FStaticMeshCompilingManager::FinishCompilation(TArrayView<…>) StaticMeshCompiler.cpp:406
UStaticMesh::WaitUntilAsyncPropertyReleased(EStaticMeshAsyncProperties) StaticMesh.cpp:3494
UStaticMesh::GetNavCollision() StaticMesh.cpp:7799
UInstancedStaticMeshComponent::GetInstanceNavigationBounds() InstancedStaticMesh.cpp:5385
UInstancedStaticMeshComponent::CalcBoundsImpl(const UE::Math::TTransform<…> &, bool) InstancedStaticMesh.cpp:2686
UInstancedStaticMeshComponent::CalcAndCacheNavigationBounds() InstancedStaticMesh.cpp:2679
UInstancedStaticMeshComponent::UpdateBounds() InstancedStaticMesh.cpp:2720
UPrimitiveComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) PrimitiveComponent.cpp:608
UStaticMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext *) StaticMeshComponent.cpp:839
UActorComponent::RecreateRenderState_Concurrent() ActorComponent.cpp:1845
UActorComponent::DoDeferredRenderUpdates_Concurrent() ActorComponent.cpp:1921
`UWorld::SendAllEndOfFrameUpdates'::`2'::<lambda_3>::operator()() LevelTick.cpp:1135
UWorld::SendAllEndOfFrameUpdates() LevelTick.cpp:1152
UEditorEngine::Tick(float, bool) EditorEngine.cpp:2166
UUnrealEdEngine::Tick(float, bool) UnrealEdEngine.cpp:547
FEngineLoop::Tick() LaunchEngineLoop.cpp:5915
[Inlined] EngineTick() Launch.cpp:61
GuardedMain(const wchar_t *) Launch.cpp:182
LaunchWindowsStartup(HINSTANCE__ *, HINSTANCE__ *, char *, int, const wchar_t *) LaunchWindows.cpp:247
WinMain(HINSTANCE__ *, HINSTANCE__ *, char *, int) LaunchWindows.cpp:298
[Inlined] invoke_main() 0x00007ff7746da35a
__scrt_common_main_seh() 0x00007ff7746da339
<unknown> 0x00007ff9cd5f257d
<unknown> 0x00007ff9cf3eaa58

[Attachment Removed]

Hi there,

Thank you for the report.

After testing with the latest version, I think the issue has been resolved as of 5.6. The fix adds a check for IsCompiling in UInstancedStaticMeshComponent::UpdateBounds, which prevents the crash.

Here is the link to the related change on GitHub in case you’d like to apply it to your own project.

https://github.com/EpicGames/UnrealEngine/commit/010146383e8c6eec2df9b2184c6289376a3cafb1

Best regards,

Henry Liu

[Attachment Removed]