TSharedPtr crash on exit game, traced to FWindowsApplication::ShutDownAfterError TaskbarList WindowsApplication.cpp line #234

Windows 7 64;
MS VStudio 2015;
Unreal Engine 4.17.1

I’ve been getting a crash when I exit my application, whether running PIE or standalone.

I trigger application shutdown via Kismet:

	UKismetSystemLibrary::QuitGame(this, this, EQuitPreference::Type::Quit);

Shutdown takes a long time, and ultimately freezes. I have to call up the Task Manager to get out of the game/editor window (Ctrl-Alt-Del), and I get a windows dialog informing me Unreal has crashed, and another window tracing the crash to an exception failure at Source\Runtime\Core\Public\Templates\SharedPtr.h line 824; which as it turns out is the operater* assignment for TSharedPtr.

	/**
	 * Dereference operator returns a reference to the object this shared pointer points to
	 *
	 * @return  Reference to the object
	 */
	822 FORCEINLINE typename FMakeReferenceTo<ObjectType>::Type operator*() const
	824 {
	825	check( IsValid() );    <<<<---- this check fails
	826	return Object;
	827}

I painstakingly pored over my entire codebase and removed all instances of TSharedPtr in the hopes of eliminating the crash, and then reinstating them until I found the issue; but when debugging I’m not led to anywhere in my code, I get a nullptr exception in Source\Runtime\Core\Private\Windows\WindowsApplication.cpp, line 234:

228 void FWindowsApplication::ShutDownAfterError()
229 {
230	// Restore accessibility shortcuts and remove the saved state from the .ini
231	AllowAccessibilityShortcutKeys(true);
232	GConfig->EmptySection(TEXT("WindowsApplication.Accessibility"), GEngineIni);
233
234	TaskbarList = nullptr;   <<<<<<< crashes here; nullptr exception
235}

TaskbarList is, in fact, a TSharedPtr; declared at Source\Runtime\Core\Public\Windows\WindowsApplication.h line 499:

	499 TSharedPtr<FTaskbarList> TaskbarList;

This is a showstopper for me, and I’m at a loss as to how to continue.

Any ideas?

Hey -

Can you provide the callstack and log files from the crash? When you removed the TSharedPtr’s from your code, did you still get the crash on exit? Are you able to reproduce this crash in a new project? If so, can you provide the setup/repro steps to help me reproduce the crash locally?

When I removed the TSharedPtrs I got the same crash within SharedPtr.h. I don’t have the logs for those crashes any longer. I think the last call before attempting to log the crash was shutting something down into the movie player, but I’m not certain. I do know that the application exit procedure began “as requested” and the shutdown procedure was proceeding as normal ( I know this isn’t particularly helpful, sorry).
I created a new, empty level within my project and ran it with the default GameMode and PlayerController and had no crash when I exited that. When I pulled my custom GameMode and into the empty level and ran that I got the same crash when exiting the PIE session, but instead of tracking to SharedPtr.h it occurred in String.h (or UnrealString.h - sorry, I neglected to record the exact filename). So there’s something in my codebase that is exposing the crash; or somehow I’m perverting the memory.

At this point I’ve created a new project and moving my core framework classes into it and re-implementing features one piece at a time until I track down where the issue is being introduced.

I’ll post an update and callstack when I get there.

I found what was leading to the crash during shutdown.

My custom keeps track of which widgets are available for focus in the viewport. When a widget is destroyed, it informs the during the BeginDestroy method it can no longer be focused. When a widget releases focus, the checks if any other widgets exist within the viewport that should receive focus, then sets user focus to the highest priority found widget or - if none were found - returns focus to the game:

FInputModeGameOnly NewInputMode = FInputModeGameOnly();
SetInputMode(NewInputMode );
FSlateApplication::Get().SetUserFocusToGameViewport(PlayerIndex);

During game shut down, a null world reference would be accessed.

I was able to prevent this by setting a flag when exiting the application and performing a check for that flag before triggering the focus change.

Should a request for focus change when the game is shutting down cause a fatal error?


The problem I had regarding UnrealString was unrelated, but caused by my tracking this error down. In removing all references to TSharedPtr I had RequestAsyncLoads tell the FStreamableManager to manage FStreamHandles, rather than doing so manually. I bind a lambda to the delegate, and release the handles during BeginDestroy when an object has active load requests - but since I stopped managing the handles they were never released when objects were destroyed, so as the game shut down it would call a lambda bound to a collected object. I log failed async loads using an FName id, but since the FName was garbage it wasn’t found within the FName index and would return an empty string. The crash then occurred when I tried to append the returned string to my log message:

FString LogMessage = TEXT("Async load failed for asset") + Name.ToString();

The append method called via the “+” operator performs a check(Count) for the length of the string and issues a fatal error if it has zero length.

I’m not convinced this is the best behavior here.

To explicitly answer your question, the editor should not crash when exiting PIE. As I mentioned, I can only speculate that this is what is happening without the crash logs. If adding the if() check does not prevent the crash, please provide the logs along with reproduction step for me to setup a small project locally or provide a small sample project that demonstrates the crash.

Hey -

Based on the lines of code provided, it appears to be the SetInputMode call that contains a GetWorld(). It sound to me like what is happening is that when you exit PIE the game viewport, which is itself a widget, gets destroyed which then calls your code above. Since the viewport has already been destoryed, this is why the GetWorld fails (without seeing the crash logs I can only guess this is what is happening). Adding an if(GetWorld()) before SetInputMode(NewInputMode); should ensure that the world exists before trying to change input focus and should prevent the crash on exit.

Cheers

As I said:

"I was able to prevent this by setting a flag when exiting the application and performing a check for that flag before triggering the focus change.

Should a request for focus change when the game is shutting down cause a fatal error?"

I.E. - Requesting focus change during game shut down causes a fatal error - is this appropriate behavior? I’m not asking if PIE should crash on exit generically, of course it shouldn’t. I’m questioning the decision to throw a fatal exception here and in this case and with this messaging.

Rather than failing out with a cryptic, generic error message, I suggest adding the GetWorld check within the focus request and a helpful warning/error message if it fails.

In my experience, UE4 error messaging is often unhelpful or outright misleading, manifesting as a very generic message (e.g. “!IsInvalid()”) and a line number within a generic data type (e.g. TSharedPtr) that could be coming from any number of locations within the code. This could be ameliorated with more helpful messages further up the pipeline - and since the error checking is often performed as a macro that doesn’t manifest itself within shipping code, there is no performance penalty; but there could be great productivity benefit.

I began having this crash after enabling the Replay Tracks plugin. It crashed every time I closed a widget blueprint window.