Context
ActorComponents can schedule an end-of-frame update for themselves by calling UWorld::MarkActorComponentForNeededEndOfFrameUpdate. The UWorld will iterate all those actor components once per tick in:
UWorld::SendAllEndOfFrameUpdates()
which will iterate various actor component arrays of UWorld and call virtual functions like:
Component->OnPreEndOfFrameSync();
Those component arrays should not be modified during iteration, at least according to how the iteration is currently implemented, for example:
for (UActorComponent* Component : ComponentsThatNeedPreEndOfFrameSync) { if (Component) { ... // I.e: inside OnPreEndOfFrameSync ComponentsThatNeedPreEndOfFrameSync should not be modified Component->OnPreEndOfFrameSync(); ... } }
Problem
Users have reported crashes from ComponentsThatNeedPreEndOfFrameSync being modified during iteration. See reported callstack, which demonstrates USkeletalMeshComponent::HandleExistingParallelClothSimulation() calling FTaskGraphInterface::WaitUntilTaskCompletes(). This is problematic since that can trigger any arbitrary task graph tasks, which may modify ComponentsThatNeedPreEndOfFrameSync.
Suggestions
Avoid USkeletalMeshComponent::HandleExistingParallelClothSimulation() calling FTaskGraphInterface::WaitUntilTaskCompletes(), or make local copies of arrays in UWorld::SendAllEndOfFrameUpdates() for safe iteration. If we choose to fix it in UWorld, we should probably do the same for:
ComponentsThatNeedPreEndOfFrameSync ComponentsThatNeedEndOfFrameUpdate ComponentsThatNeedEndOfFrameUpdate_OnGameThread
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-207947 in the post.
6 |
Component | UE - Gameplay - Components |
---|---|
Affects Versions | 5.3 |
Target Fix | 5.6 |
Created | Feb 23, 2024 |
---|---|
Updated | Sep 25, 2024 |