Hi, I believe there’s a race condition in GetFunctionSig_Write() where multiple worker threads can progress past if (!Sig.IsValid()) and stomp on each other writing to the static FNiagaraVariable EmitVar (and potentially the static FNiagaraFunctionSignature Sig). We have seen this manifest when many Effect Instances using Data Channel write are spawned at the same time from a single system.
To mitigate, I moved the signature initialisation inside a static lambda.
static const FNiagaraFunctionSignature OutSig = []
{
FNiagaraFunctionSignature Sig;
static FNiagaraVariable EmitVar(FNiagaraTypeDefinition::GetBoolDef(), TEXT("Emit"));
EmitVar.SetValue(FNiagaraBool(true));
Sig.Name = TEXT("Write");
#if WITH_EDITORONLY_DATA
NIAGARA_ADD_FUNCTION_SOURCE_INFO(Sig)
Sig.Description = LOCTEXT("WriteFunctionDescription", "Writes data into the Data Channel at a specific index. Values in the DataChannel that are not written here are set to their defaults. Returns success if the index was valid and data was written into the Data Channel.");
#endif
Sig.bMemberFunction = true;
Sig.bRequiresExecPin = true;
Sig.bWriteFunction = true;
Sig.bSupportsGPU = false;//Cannot use direct index writes on GPU as we write into one shared buffer with all DIs using the same NDC data.
Sig.AddInput(FNiagaraVariable(FNiagaraTypeDefinition(UNiagaraDataInterfaceDataChannelWrite::StaticClass()), TEXT("DataChannel interface")));
Sig.AddInput(EmitVar, LOCTEXT("ExecuteWriteFlagTooltip", "If true then the write is executed, if false then this call is ignored and no write occurs."));
Sig.AddInput(FNiagaraVariable(FNiagaraTypeDefinition::GetIntDef(), TEXT("Index")));
Sig.AddOutput(FNiagaraVariable(FNiagaraTypeDefinition::GetBoolDef(), TEXT("Success")));
Sig.RequiredInputs = IntCastChecked<int16>(Sig.Inputs.Num());//The user defines what we write in the graph.
return Sig;
}();
return OutSig;
[Attachment Removed]