Crash in UObjectArray during level load

Hi All,
We hit an odd crash during the async loading code. Callstack is below.

Main points:

  1. StaticAllocateObject is being called in the Async loading thread.

  2. It enters the following if statement (ln 2447)
    if (!bCreatingCDO && (!bCanRecycleSubobjects || !Obj->IsDefaultSubobject()))

  3. It enters Obj->~UObject();

  4. This ends up calling FUObjectArray::FreeUObjectIndex

  5. It hits the check statement at the top due to it not being a game or GC thread.

The object in our crash was a UMoviePlayer inside of a UActorSequence.

Callstack:

 ReportAssert(const wchar_t * ErrorMessage, int NumStackFramesToIgnore) Line 1627	C++
    FWindowsErrorOutputDevice::Serialize(const wchar_t * Msg, ELogVerbosity::Type Verbosity, const FName & Category) Line 79	C++
    FOutputDevice::LogfImpl(const wchar_t * Fmt, ...) Line 61	C++
    AssertFailedImplV(const char * Expr, const char * File, int Line, const wchar_t * Format, char * Args) Line 104	C++
    FDebug::CheckVerifyFailedImpl(const char * Expr, const char * File, int Line, const wchar_t * Format, ...) Line 461	C++
    FUObjectArray::FreeUObjectIndex(UObjectBase * Object) Line 282	C++
    UObjectBase::~UObjectBase() Line 131	C++
    StaticAllocateObject(const UClass * InClass, UObject * InOuter, FName InName, EObjectFlags InFlags, EInternalObjectFlags InternalSetFlags, bool bCanRecycleSubobjects, bool * bOutRecycledSubobject, UPackage * ExternalPackage) Line 2482	C++
    StaticConstructObject_Internal(const FStaticConstructObjectParameters & Params) Line 3190	C++
    FObjectInstancingGraph::GetInstancedSubobject(UObject * SourceSubobject, UObject * CurrentValue, UObject * CurrentObject, bool bDoNotCreateNewInstance, bool bAllowSelfReference) Line 228	C++
    FObjectInstancingGraph::InstancePropertyValue(UObject * ComponentTemplate, UObject * CurrentValue, UObject * Owner, bool bIsTransient, bool bCausesInstancing, bool bAllowSelfReference) Line 299	C++
    FObjectPropertyBase::InstanceSubobjects(void * Data, const void * DefaultData, UObject * InOwner, FObjectInstancingGraph * InstanceGraph) Line 52	C++
    UStruct::InstanceSubobjectTemplates(void * Data, const void * DefaultData, UStruct * DefaultStruct, UObject * Owner, FObjectInstancingGraph * InstanceGraph) Line 2155	C++
    FObjectInitializer::InstanceSubobjects(UClass * Class, bool bNeedInstancing, bool bNeedSubobjectInstancing) Line 2937	C++
    FObjectInitializer::PostConstructInit() Line 2851	C++
    FObjectInitializer::~FObjectInitializer() Line 2705	C++
    StaticConstructObject_Internal(const FStaticConstructObjectParameters & Params) Line 3196	C++

I’ve modified the check to allow for this to happen on the async loading thread, as this seems to be expected under certain circumstances.

// ILLFONIC CHANGE BEGIN - chance.lyon - Allow this to happen in the async loading thread. This can get called from UOBjectGlobals ln 2481: Obj->~UObject();
	//check(IsInGameThread() || IsInGarbageCollectorThread() );
	check(IsInGameThread() || IsInGarbageCollectorThread() || IsInAsyncLoadingThread());
// ILLFONIC CHANGE END

Is this workaround correct? Or is this crash indicative of a deeper issue?

Thanks,

  • Chance
1 Like

I hit this exact issue with the same crash log. I wonder if this issue is resolved in the latest version of the engine. BTW, I used actor sequence as well in my game. So,… can loading actors with actor sequence synchronously be another approach? Or, sync’ing only the actor sequence loading part within async loading. The modified check condition would be applied to all other cases, it will probably not something we can do for the long term…