UE4.8 Freezes when I kill a thread

Hi,

Consider the following scenario :

1 - I have a class (class X ) derived from Frunnable.

2 - class X has a member variable of FrunnableThread

3 - I have a class ( class Y ) which is of type UActorComponent

4 - Class Y has member pointer to an instance of class X

Now, there are two function that are public and I use in class Y and they are accessible in blueprints

1 - starting a new instance of frunnable thread in class X

2 - killing the running Thread

When I try to kill the running thread with Kill(true) UE4 gets not responding.
funnily enough when I compile the code in debug mode there is no issue.

I want to know if you can help me solve this problem ? is it because I am trying to kill it in blueprints ? if so then how can I solve this problem ?

PS : it is a very basic code, so I mainly do nothing. it is just a test on running and killing threads via blueprints

This question is confusing…
Can you clarify, or send a screen shot of the error or code that causes the error?

killing a class(which would remove all instances from the game, so is not really a good idea) You could also remove the class/component from the actor

killing threads?(not sure why you would want to mess with this if trying to “kill” a class or actor)

killing actors? you could always destroy them

oh it was a mistype. I do not kill any class, I kill the running thread using a blueprint node which calls a function in the Frunnable class that calls Kill over FrunnableThread onject.
I will modify the description now. As for the code I can provide it by the evening

#pragma region FRunnable functionalities

    bool myKinect::Init()
    {
    	stopRunnable = false;
    	return true;
    }

    uint32 myKinect::Run()
    {
    	FPlatformProcess::Sleep(0.03);
    
    	while (!stopRunnable)
    	{
    		;// calculate;
    	}
    
    	return 0;
    }
    
    void myKinect::Stop()
    {
    	stopRunnable = true;
    }
    
    void myKinect::Exit()
    {
    
    }
    
    void myKinect::StartSensor()
    {
    	if (!kinectThread)
    	{
    		kinectThread = FRunnableThread::Create(this, TEXT("FKinectThread"), 0, EThreadPriority::TPri_AboveNormal);
    	}
    }
    
    void myKinect::StopSensor()
    {
    	if (kinectThread) {
    		kinectThread->Kill(true);
    		delete kinectThread;
    		kinectThread = nullptr;
    	}
    }
#pragma endregion



// now here is the UactorComponent that runs the thread in myKinect class

    void UMyKinectHandlerComponent::BeginPlay()
    {
    	Super::BeginPlay();
    
 
    	kinectHandler = myKinect::getHandler(); // this is a singleton
    
    }

    
    
    // Called every frame
    void UMyKinectHandlerComponent::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
    {
    	Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
    
    	// ...
    }

#pragma region Kinect Handling Functions

void UMyKinectHandlerComponent::StartSensor()
{	
	kinectHandler->StartSensor();
}

void UMyKinectHandlerComponent::StopSensor()
{
	kinectHandler->StopSensor(); // crash happens whe this is getting called
}

#pragma endregion

I have posted the code under the main question for you to have a look :slight_smile:

I have found out that the problem is with Kill(true). meaning that if I call it Kill(false) then it wouldn’t be a problem.
UE4 freezes due to stuck in WaitForSingleObject(Thread,INFINITE); in the following function
Interestingly there is no problem with debug mode :frowning:

virtual bool Kill( bool bShouldWait = false ) override
    	{
    		check(Thread && "Did you forget to call Create()?");
    		bool bDidExitOK = true;
    		// Let the runnable have a chance to stop without brute force killing
    		if (Runnable)
    		{
    			Runnable->Stop();
    		}
    		// If waiting was specified, wait the amount of time. If that fails,
    		// brute force kill that thread. Very bad as that might leak.
    		if (bShouldWait == true)
    		{
    			// Wait indefinitely for the thread to finish.  IMPORTANT:  It's not safe to just go and
    			// kill the thread with TerminateThread() as it could have a mutex lock that's shared
    			// with a thread that's continuing to run, which would cause that other thread to
    			// dead-lock.  (This can manifest itself in code as simple as the synchronization
    			// object that is used by our logging output classes.  Trust us, we've seen it!)
    			WaitForSingleObject(Thread,INFINITE);
    		}
    		// Now clean up the thread handle so we don't leak
    		CloseHandle(Thread);
    		Thread = NULL;
    
    		return bDidExitOK;
    	}

#Let the Thread complete

You should be allowing the thread to complete!

See the code in my PrimeNumber multi thread example!

void FPrimeNumberWorker::EnsureCompletion()
{
	Stop();
	Thread->WaitForCompletion();
}
 
void FPrimeNumberWorker::Shutdown()
{
	if (Runnable)
	{
		Runnable->EnsureCompletion();
		delete Runnable;
		Runnable = NULL;
	}
}

:slight_smile:

Rama

Hi,

I have found the issue, and the solution.
there is no need of the thread to be completed at all. the problem is that since the stop function of the thread is using windows standard functionalities the cpp or at least the part in charge of stopping should be wrapped in
#include “AllowWindowsPlatformTypes.h” and #include “HideWindowsPlatformTypes.h”. it will solve the problem.

#include "DepthKinect2Plugin.h"
#include "myKinect.h"
#include "AllowWindowsPlatformTypes.h"


myKinect::myKinect()
{
  ...
}

myKinect::~myKinect()
{
  ...
}

bool myKinect::Init()
{
	...
}

uint32 myKinect::Run()
{
	...
}

void myKinect::Stop()
{
	...
}

void myKinect::Exit()
{
	...
}

bool myKinect::IsRunning()
{
	...
	
}

void myKinect::StartSensor()
{
	if (!kinectThread)
	{
		kinectThread = FRunnableThread::Create(this, TEXT("FKinectThread"), 0, EThreadPriority::TPri_Normal);
		UE_LOG(LogClass, Log, _T("Kinect Thread is Created Successfully"));
	}
}

void myKinect::StopSensor()
{
	UE_LOG(LogClass, Log, _T("Stop Sensor Function for Kinect Thread is Called"));
	if (kinectThread) {

		kinectThread->Kill(true);
		
		delete kinectThread;

		kinectThread = nullptr;
	}
}

#include "HideWindowsPlatformTypes.h"

although your code does not make issue and it is ok the problem is that for your code the thread will and should finish by finishing its work. I might want to have a code which stops the thread on demand. I have posted the solution I have had found for the problem