Hello there,
I am working on a multithreaded plugin, and it works, but keeps crashing when I try to end a thread.
This is the error I get:
Access violation - code c0000005 (first/second chance not available)
UE4Editor_CoverGeneration!UE4Function_Private::TFunctionRefCaller<<lambda_2a64e326e72d1a19660cfad29154444e>,void __cdecl(void)>::Call() [c:\program files\epic games\ue_4.15\engine\source\runtime\core\public\templates\function.h:244]
UE4Editor_Core!TGraphTask<FAsyncGraphTask>::ExecuteTask() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\public\async\taskgraphinterfaces.h:883]
UE4Editor_Core!FNamedTaskThread::ProcessTasksNamedThread() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\private\async\taskgraph.cpp:954]
UE4Editor_Core!FNamedTaskThread::ProcessTasksUntilIdle() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\private\async\taskgraph.cpp:716]
UE4Editor_Engine!FFrameEndSync::Sync() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\unrealengine.cpp:8430]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3151]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\launch.cpp:166]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:134]
UE4Editor!WinMain() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:210]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:264]
kernel32
ntdll
I have done some searching, and it seems that access violation occurs when accessing a pointer that points to nothing. But I cannot find a pointer that doesn’t have a checker surrounding it.
I also see my RAM ussage skyrocket right before the crash.
This is the last bit of log I get:
[2017.05.07-20.13.03:589][353]LogTemp:Warning: ThreadManagerThread: Entered infinte loop
[2017.05.07-20.13.03:593][353]LogTemp:Warning: ACoverAI_BasicGameMode destructor
[2017.05.07-20.13.03:593][353]LogTemp:Warning: ThreadManagerThread: Shutdown
[2017.05.07-20.13.03:593][353]LogTemp:Warning: Runnable == true
[2017.05.07-20.13.03:593][353]LogTemp:Warning: ThreadManagerThread: Cast to ACoverAI_BasicGameMode
[2017.05.07-20.13.03:594][353]LogTemp:Warning: ThreadManagerThread: Ensure completion
[2017.05.07-20.13.03:594][353]LogTemp:Warning: ThreadManagerThread: Entered infinte loop
[2017.05.07-20.13.03:594][353]LogTemp:Warning: ThreadManagerThread: Cast to ACoverAI_BasicGameMode
[2017.05.07-20.13.03:594][353]LogTemp:Warning: ThreadManagerThread: Entered infinte loop
[2017.05.07-20.13.03:594][353]LogTemp:Warning: ThreadManagerThread: Stop
[2017.05.07-20.13.03:595][353]LogTemp:Warning: ThreadManagerThread: Cast to ACoverAI_BasicGameMode
[2017.05.07-20.13.03:595][353]LogTemp:Warning: ThreadManagerThread: Exit
[2017.05.07-20.13.03:595][353]LogTemp:Warning: ThreadManagerThread Destructor
[2017.05.07-20.13.03:595][353]LogTemp:Warning: ThreadManagerThread: Stop
The only weird thing I see is that Stop is called twice.
And here is my code for shut down in the threadclass.cpp:
ThreadManagerThread::~ThreadManagerThread()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadManagerThread Destructor"));
if (Thread)
{
delete Thread;
Thread = NULL;
}
}
ThreadManagerThread* ThreadManagerThread::JoyInit()
{
Runnable = NULL;
UE_LOG(LogTemp, Warning, TEXT("ThreadMangerThread: JoyInit"));
//Create new instance of thread if it does not exist
// and the platform supports multi threading!
if (!Runnable && FPlatformProcess::SupportsMultithreading())
{
Runnable = new ThreadManagerThread();
}
return Runnable;
}
//Make sure thread starts correctly
bool ThreadManagerThread::Init()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadMangerThread: Init"));
//StopTaskCounter.Set(0);
return true;
}
//stop
void ThreadManagerThread::Stop()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadManagerThread: Stop"));
StopTaskCounter.Increment();
return;
}
//Called after Run() returned a value
void ThreadManagerThread::Exit()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadManagerThread: Exit"));
//Shutdown();
return;
}
void ThreadManagerThread::EnsureCompletion()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadManagerThread: Ensure completion"));
Stop();
if (Thread)
{
Thread->WaitForCompletion();
}
return;
}
//Stop the thread
void ThreadManagerThread::Shutdown()
{
UE_LOG(LogTemp, Warning, TEXT("ThreadManagerThread: Shutdown"));
if (Runnable)
{
UE_LOG(LogTemp, Warning, TEXT("Runnable == true"));
Runnable->EnsureCompletion();
delete Runnable;
Runnable = NULL;
}
return;
}
And this is what I use to call Shutdown inside my gamemodes destructor:
if (ThreadManagerThread::Runnable)
{
//ThreadManagerThread::Runnable->Thread->Kill(true);
ThreadManagerThread::Runnable->Shutdown();
}
Do I need to check if my StopTaksCounter is still valid in the Stop function and if so, how do I do it?
Or am I doing something wrong?
Thanks for your time.