Description

I was working with a licensee on something unrelated, and ran into this niagara threading crash. It looks like UNiagaraDataInterfaceSpline::SampleSplinePositionByUnitDistance on one of the niagara helper threads is accessing USplineComponent's internal curve data at the same time it is being modified in the game thread. In the case I caught, the output error was "Array index out of bounds: 117 from an array of size 511" and the main thread was waiting, so I think the stack is from right after the thread data corruption happened. Specifically it looks like the game thread reallocated the Points TArray inside an FInterpCurve because a new point was added to it, while the niagara thread was accessing the old one.

This issue might be isolated to the spline data interface or could be with other interfaces. In general anything pulling data out of a component in another thread is potentially unsafe unless it's synchronized with the game thread somehow. This is a thread timing issue so will not be trivial to reproduce. The licensee content was a spline component being modified by blueprints, with points added very frequently

Steps to Reproduce

There's no hard repro, this is a crash I saw while working with a licensee and is also an intermittent thread issue. Vague repro steps:

  1. Create a niagara emitter that uses splinecomponent data, in this case SampleSplinePositionByUnitDistance
  2. Constantly update that spline component on the main thread every frame, adding and removing a lot of points so it reallocates array
  3. Crash if niagara thread runs at same time as game thread
Callstack

[Inline Frame] UE4Editor-Engine.dll!TArray<FInterpCurvePoint<float>,TSizedDefaultAllocator<32> >::RangeCheck(int Index) Line 674
[Inline Frame] UE4Editor-Engine.dll!TArray<FInterpCurvePoint<float>,TSizedDefaultAllocator<32> >::operator[](int) Line 731
[Inline Frame] UE4Editor-Engine.dll!FInterpCurve<float>::GetPointIndexForInputValue(const float) Line 274
UE4Editor-Engine.dll!FInterpCurve<float>::Eval(const float InVal, const float & Default) Line 301
UE4Editor-Engine.dll!USplineComponent::GetLocationAtDistanceAlongSpline(float Distance, ESplineCoordinateSpace::Type CoordinateSpace) Line 1088 C++
UE4Editor-Niagara.dll!UNiagaraDataInterfaceSpline::SampleSplinePositionByUnitDistance<FNDITransformHandler,VectorVM::FExternalFuncRegisterHandler<float> >(FVectorVMContext & Context) Line 399
UE4Editor-VectorVM.dll!VectorVM::Exec::__l2::<lambda>(int BatchIdx) Line 2319
UE4Editor-VectorVM.dll!VectorVM::Exec(const unsigned char * ByteCode, const unsigned char * OptimizedByteCode, int NumTempRegisters, int ConstantTableCount, const unsigned char * const * ConstantTable, const int * ConstantTableSizes, TArrayView<FDataSetMeta> DataSetMetaTable, TBaseDelegate<void,FVectorVMContext &> * ExternalFunctionTable, void * * UserPtrTable, int NumInstances, const TArray<TStatId,TSizedDefaultAllocator<32> > & StatScopes) Line 2460
UE4Editor-Niagara.dll!FNiagaraScriptExecutionContext::Execute(unsigned int NumInstances, const FScriptExecutionConstantBufferTable & ConstantBufferTable) Line 217
UE4Editor-Niagara.dll!FNiagaraEmitterInstance::Tick::__l193::<lambda>(int Num, const wchar_t * DumpLabel) Line 1497
UE4Editor-Niagara.dll!FNiagaraEmitterInstance::Tick(float DeltaSeconds) Line 1525
UE4Editor-Niagara.dll!FNiagaraSystemInstance::Tick_Concurrent() Line 2076
[Inline Frame] UE4Editor-Niagara.dll!FNiagaraSystemInstanceAsyncTask::DoTask(ENamedThreads::Type) Line 242
UE4Editor-Niagara.dll!TGraphTask<FNiagaraSystemInstanceAsyncTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > & NewTasks, ENamedThreads::Type CurrentThread) Line 849
[Inline Frame] UE4Editor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32> > & CurrentThread, ENamedThreads::Type) Line 516
UE4Editor-Core.dll!FTaskThreadAnyThread::ProcessTasks() Line 1039
UE4Editor-Core.dll!FTaskThreadAnyThread::ProcessTasksUntilQuit(int QueueIndex) Line 863
[Inline Frame] UE4Editor-Core.dll!FTaskThreadBase::Run() Line 528
UE4Editor-Core.dll!FTaskThreadAnyThread::Run() Line 940
UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 86
UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 27

 

Assertion failed: (Index >= 0) & (Index < ArrayNum) [Link Removed] [Line: 674]
Array index out of bounds: 117 from an array of size 511

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-96884 in the post.

1
Login to Vote

Fixed
ComponentUE - Rendering - Niagara
Affects Versions4.25.3
Target Fix4.26
Fix Commit14615380
Release Commit14615380
CreatedAug 13, 2020
ResolvedOct 29, 2020
UpdatedApr 28, 2021