UGameFrameworkComponent - GetGameInstance on EndPlay while destroying

Hey!

I have experienced a crash today while trying to get the game instance from an actor in the EndPlay function. It was a memory crash and I think that it could be provoked by the function GetGameInstance in UGameFrameworkComponent

As you can see in the image there is a missing IsValid check before, so I think that the owner is pending to kill and the memory may not be in accessible at this point, could it be true? Would it be safe to add a IsValid there?

[Image Removed]

Hey Victor, this sounds like a crash we would want to fix. Can you provide the callstack of that crash?

Hey Zhi Kang Shao,

Suddenly I do not have a proper way to reproduce this and I just got a Sentry ticket without too much context, this is what I was able to extract and It doesn’t seem to fit with what the Sentry data displays (see image):

`[2025.04.23-14.20.23:653][398]LogOutputDevice: Warning:

Script Stack (0 frames) :

[2025.04.23-14.20.23:664][398]LogStats: FPlatformStackWalk::StackWalkAndDump - 0.006 s

[2025.04.23-14.20.23:675][398]LogOutputDevice: Error: === Handled ensure: ===

[2025.04.23-14.20.23:686][398]LogOutputDevice: Error:

[2025.04.23-14.20.23:697][398]LogOutputDevice: Error: Ensure condition failed: false || (LocalWorld != nullptr) [File:C:\BuildAgent\work\454e66fa4e22255b\Engine\Plugins\Runtime\ModularGameplay\Source\ModularGameplay\Private\Components\GameFrameworkComponentManager.cpp] [Line: 415]

[2025.04.23-14.20.23:708][398]LogOutputDevice: Error:

[2025.04.23-14.20.23:719][398]LogOutputDevice: Error: Stack:

[2025.04.23-14.20.23:730][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fe2ebc4 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:741][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fe23d80 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:752][398]LogOutputDevice: Error: [Callstack] 0x00007ff639c28faf EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:763][398]LogOutputDevice: Error: [Callstack] 0x00007ff641449620 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:774][398]LogOutputDevice: Error: [Callstack] 0x00007ff63febd49e EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:785][398]LogOutputDevice: Error: [Callstack] 0x00007ff63febedf4 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:796][398]LogOutputDevice: Error: [Callstack] 0x00007ff63feb5c54 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:807][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fe9caee EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:818][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fe9ca53 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:829][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fea0153 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:840][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fea0061 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:851][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fee2736 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:862][398]LogOutputDevice: Error: [Callstack] 0x00007ff63fee32a0 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:873][398]LogOutputDevice: Error: [Callstack] 0x00007ff63e365a7d EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:884][398]LogOutputDevice: Error: [Callstack] 0x00007ff63a55e953 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:895][398]LogOutputDevice: Error: [Callstack] 0x00007ff63a4fdb0b EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:906][398]LogOutputDevice: Error: [Callstack] 0x00007ff63a4581e3 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:917][398]LogOutputDevice: Error: [Callstack] 0x00007ff63a4a2616 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:928][398]LogOutputDevice: Error: [Callstack] 0x00007ff63a472edb EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:939][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f0c53d6 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:950][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f092bbd EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:961][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f03e484 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:972][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f0bdd7e EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:983][398]LogOutputDevice: Error: [Callstack] 0x00007ff63e6484ad EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.23:994][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f39d585 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:005][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f3aaebc EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:016][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f3aaf8a EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:028][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f3ad6d2 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:039][398]LogOutputDevice: Error: [Callstack] 0x00007ff63f3ba104 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:050][398]LogOutputDevice: Error: [Callstack] 0x00007ff644400fa2 EVEVanguardClient.exe!UnknownFunction

[2025.04.23-14.20.24:061][398]LogOutputDevice: Error: [Callstack] 0x00007ffc30b77374 KERNEL32.DLL!UnknownFunction

[2025.04.23-14.20.24:072][398]LogOutputDevice: Error: [Callstack] 0x00007ffc3191cc91 ntdll.dll!UnknownFunction

[2025.04.23-14.20.24:083][398]LogOutputDevice: Error:

[2025.04.23-14.20.24:104][398]LogStats: SubmitErrorReport - 0.000 s

[2025.04.23-14.20.24:115][398]LogStats: SendNewReport - 0.000 s

[2025.04.23-14.20.24:126][398]LogStats: FDebug::EnsureFailed - 1.899 s`I hope this helps.

Best,

Victor Macho.

Checking the error It could also be required to add a IsValid here in UGameFrameworkComponentManager::RemoveExtensionHandler line 412

UGameInstance* LocalGameInstance = GetGameInstance(); if (ensure(LocalGameInstance))

Hey Victor, reading your report and looking at the Sentry screenshot, it seems there are two crashes to address.

1) In the Sentry screenshot: the callstack contains an AtlasPawnExtensionComponent being destroyed during a garbage collection pass. It’s odd that EndPlay is entered there because EndPlay should have already been called when the level was unloaded or when the actor was first destroyed. The EndPlay on BeginDestroy is only a fallback when the intended route of calling EndPlay was missed. Does AtlasPawnExtensionComponent or any of its subclasses perhaps forget to call Super::EndPlay()?

2) It’s possible that UGameFrameworkComponentManager::RemoveExtensionHandler is triggering on application shutdown since the destructor ~FComponentRequestHandle() calls it. I expect that would result in a failing ensure, which would halt execution if you’re running the editor with a debugger attached, but not crash the application. Do you recall if that was the case?

Replacing the ensure(LocalGameInstance) in RemoveExtensionHandler with IsValid(LocalGameInstance) sounds alright to me. However for us to make the engine change, I would prefer to see the callstack if it happens again so that we know under which conditions the ~FComponentRequestHandle() destructor triggered to determine whether it’s an engine bug or a game code misuse of FComponentRequestHandle.

Hey!

Thanks for taking a look to this.

1) Yeah I understand what you mean, and I thought the same, but AtlasPawnExtensionComponent has not child classes and and this inherits from UPawnComponent (This class is a copy from Lyra project pawn readiness), and I checked EndPlay and It looks correct to me, we try to get the game instance before calling Super::EndPlay

[Image Removed]We fixed it by adding if (IsValid(World) && !World->bIsTearingDown) before so we do not try to get the game instance if we are shooting down.

2) Yeah you are right, if you check the log I pasted It shows an ensure:

Error: Ensure condition failed: false || (LocalWorld != nullptr)

so I’d say that since this provokes a hinch in the execution the person who sends me this may have confused it with a crash. Suddenly I’m not able to reproduce this and I think that since the change we did to check if the world is tearing down this didn’t show, but It could be interesting to replace the ensures by IsValid so we do not get false errors.

If I’m able to get a callstack of this issue I’ll send it to you.

Best,

Victor Macho.

Hey again, thanks for pointing me at the log again. Indeed that confirms which ensure was tripped. I’m submitting an engine change for review right now since it should not be surprising to us that if we expose TSharedPtr<FComponentRequestHandle> to game code, that the destructor ~FComponentRequestHandle() might be called during world teardown or app shutdown. I’ll aim to get this addressed in engine code. The callstack would help get the change in, but since here we are returning the TSharedPtr<FComponentRequestHandle> at which point engine code has no control over the lifetime anymore, I expect no trouble getting this merged in.

Hey again, after discussing internally our preference is to keep these as ensures but with an improved message.

Instead, the contract for FComponentRequestHandle will be that if you register a modular feature (AddComponentRequest, AddExtensionHandler) and you store the returned TSharedPtr<FComponentRequestHandle>, you must also clear that pointer before the app shuts down so before GameInstance and World become invalid. We’ll keep the ensure there to enforce good practices, but I’ll add more comments including that expectation that the dev should clean the pointer up. I hope this decision is understandable.