Async scene destructible + set material in ReceivePointDamage on destructible component = crash

Hi,
I found something interesting in 4.6.

I’m using some destructible components in BP. During normal destruction of destructible component the ReceivePointDamage comes then change some materials in hit destructible component,finally I got crash 1/3 repro.

Every destructible component is created in async scene.

Stack trace:

>	UE4Editor-Engine-Win64-Debug.dll!FBodyInstance::UpdatePhysicalMaterials() Line 373	C++
 	UE4Editor-Engine-Win64-Debug.dll!UMeshComponent::SetMaterial(int ElementIndex, UMaterialInterface * Material) Line 63	C++
 	UE4Editor-Engine-Win64-Debug.dll!UPrimitiveComponent::execSetMaterial(FFrame & Stack, void * const Result) Line 104	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UFunction::Invoke(UObject * Obj, FFrame & Stack, void * const Result) Line 3699	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::CallFunction(FFrame & Stack, void * const Result, UFunction * Function) Line 395	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::execVirtualFunction(FFrame & Stack, void * const Result) Line 1530	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!FFrame::Step(UObject * Context, void * const Result) Line 126	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::ProcessContextOpcode(FFrame & Stack, void * const Result, bool bCanFailSilently) Line 1451	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::execContext_FailSilent(FFrame & Stack, void * const Result) Line 1434	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!FFrame::Step(UObject * Context, void * const Result) Line 126	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::ProcessInternal(FFrame & Stack, void * const Result) Line 625	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::CallFunction(FFrame & Stack, void * const Result, UFunction * Function) Line 516	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::execVirtualFunction(FFrame & Stack, void * const Result) Line 1530	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!FFrame::Step(UObject * Context, void * const Result) Line 126	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::ProcessInternal(FFrame & Stack, void * const Result) Line 625	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UFunction::Invoke(UObject * Obj, FFrame & Stack, void * const Result) Line 3699	C++
 	UE4Editor-CoreUObject-Win64-Debug.dll!UObject::ProcessEvent(UFunction * Function, void * Parms) Line 927	C++
 	UE4Editor-Engine-Win64-Debug.dll!AActor::ProcessEvent(UFunction * Function, void * Parameters) Line 549	C++
 	UE4Editor-Engine-Win64-Debug.dll!AActor::ReceivePointDamage(float Damage, const UDamageType * DamageType, FVector HitLocation, FVector HitNormal, UPrimitiveComponent * HitComponent, FName BoneName, FVector ShotFromDirection, AController * InstigatedBy, AActor * DamageCauser) Line 1084	C++
 	UE4Editor-Engine-Win64-Debug.dll!AActor::TakeDamage(float DamageAmount, const FDamageEvent & DamageEvent, AController * EventInstigator, AActor * DamageCauser) Line 1632	C++

if (RigidActorAsync != NULL)
{
	SCENE_LOCK_WRITE(RigidActorAsync->getScene()); //<- crash
}

RigidActorAsync is invalid.

I read some comments about using BodyInstance in case of destructible component:

from the UDestructibleComponent::SetupFakeBodyInstance

This code is very dangerous, but at the moment I have no better solution:
Destructible component assigns PxRigidDynamic to the BodyInstance as it needs it.
Destructible PxRigidDynamic actors can be deleted from under us as PhysX sees fit.
Ideally we wouldn’t ever have a dangling pointer, but in practice this is hard to avoid.
In theory anyone using BodyInstance on a PrimitiveComponent should be using functions like GetBodyInstance - in which case we properly fix up the dangling pointer

I simply replaced

UMeshComponent::SetMaterial(int32 ElementIndex, UMaterialInterface* Material)

if (BodyInstance.IsValidBodyInstance())
{
	BodyInstance.UpdatePhysicalMaterials();
}

to:

FBodyInstance* BodyInst = GetBodyInstance();

if (BodyInst && BodyInst->IsValidBodyInstance())
{
      BodyInst->UpdatePhysicalMaterials();
}

And I’m unable to reproduce this crash 0/20.

Regards

Pierdek

Hi,

This looks right. Good catch!
Would you mind submitting this as a pull request?

Sure I can.