Crash on UNiagaraDataInterfaceChaosDestruction::BeginDestroy()

  • Activate a Chaos Destruction VFX effect during a multiplayer game, causing the call of UNiagaraDataInterfaceChaosDestruction::InitPerInstanceData
  • A new Solver is added from the SystemInstance to the Solvers Array of UNiagaraDataInterfaceChaosDestruction
  • The host starts a ServerTravel with all the clients

We can notice that the dtor of the FEventManager is called through the FChaosSolversModule::DestroySolver method that is called through the GarbageCollector. The dtor of FEventManager calls ***FEventManager::Reset()*invalidating the EventContainers Array. This series of calls can be made before the call UNiagaraDataInterfaceChaosDestruction::BeginDestroy() that is also called trough the GarbageCollector.

When UNiagaraDataInterfaceChaosDestruction::BeginDestroy() calls FEventManager::UnregisterHandler() the game crashes on ContainerLock.ReadLock(); or in checkf(EventID < EventContainers.Num(), TEXT(“Unregistering event Handler for an event ID that does not exist”));

Curiously, this seems to happen only during the server travel. If the UNiagaraDataInterfaceChaosDestruction::BeginDestroy() is called after the server travel is finished, the SolverData.Solver->GetEventManager() seems to be nullptr.

`void UNiagaraDataInterfaceChaosDestruction::BeginDestroy()
{
Super::BeginDestroy();

for (FSolverData& SolverData : Solvers)
{
Chaos::FEventManager* EventManager = SolverData.Solver->GetEventManager();
if (EventManager)
{
EventManager->UnregisterHandler(Chaos::EEventType::Collision, this);
EventManager->UnregisterHandler(Chaos::EEventType::Breaking, this);
EventManager->UnregisterHandler(Chaos::EEventType::Trailing, this);
}
}

Solvers.Reset();
}

void FEventManager::UnregisterHandler(const EEventType& EventType, const void* InHandler)
{
const FEventID EventID = (FEventID)EventType;
ContainerLock.ReadLock();
checkf(EventID < EventContainers.Num(), TEXT(“Unregistering event Handler for an event ID that does not exist”));
EventContainers[EventID]->UnregisterHandler(InHandler);
ContainerLock.ReadUnlock();
}`

Hello [mention removed]​,

I’ve been testing this scenario by spawning a Niagara FX from a ChaosBreakEvent and initiating ServerTravel while the FX is still active.

In my setup,

  • UNiagaraDataInterfaceChaosDestruction::BeginDestroy() is called.
  • SolverData.Solver->GetEventManager() does not return nullptr.
  • EventManager->UnregisterHandler(…) is executed.
  • The checkf(EventID < EventContainers.Num(), …) assertion is not triggered.

Would you be able to share a minimal project that reproduces the crash on your side? Could you also confirm whether the issue occurs in a dedicated or listen server?

Best,

Francisco