Intermittent Crash On Render Thread When Destroying Widget Component

This is a tough crash to debug because I’ve only seen this in Ship and only after we play 5-10 matches in a row. However, this is the callstack from the dump (UE 4.9.1):

 	Icon-Win64-Shipping.exe!FSlateBatchData::CreateRenderBatches() Line 291	C++
>	Icon-Win64-Shipping.exe!FSlate3DRenderer::DrawWindowToTarget_RenderThread(FRHICommandListImmediate & RHICmdList, UTextureRenderTarget2D * RenderTarget, FSlateDrawBuffer & InDrawBuffer) Line 92	C++
 	Icon-Win64-Shipping.exe!TGraphTask<`UWidgetComponent::TickComponent'::`24'::EURCMacro_UWidgetComponentRenderToTexture>::ExecuteTask(TArray<FBaseGraphTask *,FDefaultAllocator> & NewTasks, ENamedThreads::Type CurrentThread) Line 811	C++
 	Icon-Win64-Shipping.exe!FTaskThread::ProcessTasks(int QueueIndex, bool bAllowStall) Line 545	C++
 	Icon-Win64-Shipping.exe!FTaskThread::ProcessTasksUntilQuit(int QueueIndex) Line 340	C++
 	Icon-Win64-Shipping.exe!RenderingThreadMain(FEvent * TaskGraphBoundSyncEvent) Line 310	C++
 	Icon-Win64-Shipping.exe!FRenderingThread::Run() Line 411	C++
 	Icon-Win64-Shipping.exe!FRunnableThreadWin::Run() Line 74	C++
 	Icon-Win64-Shipping.exe!FRunnableThreadWin::GuardedRun() Line 31	C++

We only use the WidgetComponent in one place in our game. It is on an actor that spawns, exists in the world for several seconds, and then gets destroyed again. This leads me to believe that there’s some edge case in which the render batch data can get put on the render thread but isn’t valid anymore due to actor destruction. Does this sound plausible? Any help would be greatly appreciated.

I haven’t had this exact issue but I’ve had issues in the past where UMG slate widgets being destroyed would cause bad things to happen on the render thread. I got around these (and made an accepted pull request for code in a few places regarding this) by adding a check inside the crashing function that makes sure the target object doesn’t have the flags RF_Unreachable or RF_PendingKill set. I don’t have access to my engine source at the moment so I can’t figure out where it would be best to make this addition, but hopefully this info is enough for you to find out where to place this check, and hopefully, make a pull request on github.

Thanks Allar, this is great idea! Unfortunately, I don’t think there’s actually a UObject reference to test anywhere in the callstack because it’s a just a task that gets dispatched on the render thread and all the references are slate references. It’s possible that something there is some slate reference I could use that is marked as invalid somehow but without being more familiar with Slate and without a reliable way to reproduce this crash I’m not sure what it would be.

For now, I’m going to try to workaround the problem by setting all of the widget components to not visible for a few frames before destroying the actor they are attached to. We’ll see if the issue comes up again. I will report back.

Hi BrainDX -

I am seeing this same call stack with some PIE Editor based user projects in the wild and am beginning to try to debug and run a reproduction case. Can you give me some information about the exact setup you have? The actor that you have spawned is it a child blueprint, what type of mesh if any are you using in the Blueprint. What type of interaction do you have with the 3D Widget attached to the spawned actor? What feeds information to and from that 3D Widget?

As much as you can provide would be helpful -

Thank You

Eric Ketchum

Hi Eric,

The blueprint is an AActor, its hierarchy looks like following:

   Scene Component  

       Widget Component 1  

       Widget Component 2  

       Widget Component 3  

   Scene Component  

       Widget Component 4  

       Widget Component 5  

       Widget Component 6  

The scene components are generic, they’re just there for transform purposes. The blueprint itself does nothing all that special. On begin play, it starts a timeline which calls a ‘Set Actor Scale 3D’ to scale the widget from 0 to its final size. Then, it has a custom ‘Animate Out’ event which triggers a different timeline that also calls ‘Set Actor Scale 3D’ to scale the widget from its final size back to 0. Upon completion, it calls the Destroy Actor node. The ‘Animate Out’ event is triggered from the ‘Event Destroyed’ node of a totally different blueprint actor.

Thank You. I will construct that and see if I can replicate the crash internally.

Eric Ketchum

Just as a note, this whole flow of spawn/animate/destruct happens 3-5 times per game and it takes us about 5-10 matches to see the crash, so you’ll probably have to do a bit of stress testing to get it to trigger.

One other note I forgot about. Not sure if this can be attributed to the crash, but we are using our own subclass of UWidgetComponent, the only change is an override to the OnRegister function so that we can use our own material to draw the render texture into the world. It looks as follows:

void UIconWidgetComponent::OnRegister()
{
	Super::OnRegister();
	if ( MaskedOneSidedOverride != NULL )
	{
		MaskedMaterial_OneSided = MaskedOneSidedOverride;
	}
	if ( TranslucentOneSidedOverride != NULL )
	{
		TranslucentMaterial_OneSided = TranslucentOneSidedOverride;
	}
	UpdateMaterialInstance();
}

From looking at the dump, I can’t be sure because it’s in ship, but it appears that the issue might be that ElementBatch.GetShaderResource() is non-NULL but still invalid. In this case, the access violation is attempting to read 0x000000000000584A. If anyone has any ideas as to how that situation may be arising I can investigate.

Hi BrainDX -

We have identified the results of the crash internally and are working on implementing the fixes into the next major engine release. This issue has actually been very recently corrected by several fixes which are still in testing for integration into Main.

Thank You

Eric Ketchum

Hi Eric, could you specify the changelists that are involved with these fixes? I would like to test these out and see if they are something that I we could integrate locally until the next major engine release. Thanks!

Hi CWeaver -

There is a total of 5 separate Changelists that make up the solution to this issue. Some of the files that make up the fix are still currently in testing and being integrated from game branches of the internal engine. As soon as I can track down the Master branch GitHub commits I will post them here.

Eric Ketchum

Hey Eric, thanks for getting back to me. We have a demo coming up and are under a bit of time pressure to test out this fix on our build.

I have access to the Epic Perforce server. If you can just locate the associated changelists I can easily pull those over and test them out.

Thanks!
-Casey

Sure - I’ve posted this question (using the same subject line) in UDN.

Hey CWeaver -

Since you are a custom licensee, can you please post this request on UDN?

Eric Ketchum