I have a multithreaded C++ Windows application. The worker thread is an infinite loop waiting for events to process, one of which is a kill thread event from main thread. The problem is that sometimes it takes a really long time (think seconds) for the worker thread to receive the kill event and terminate. Other times it's very quick (milliseconds).
// Main thread code
void deactivate()
{
while (isWorkerThreadRunning)
{
// Problem: sometimes it spends a long time in this loop
logDebug("deactivate: killing worker thread");
SetEvent(killWorker);
Sleep(20);
}
}
// Worker thread code
DWORD WINAPI WorkerThreadProc(LPVOID arglist)
{
isWorkerThreadRunning = true;
logDebug("Worker thread started");
for (bool done = false; done != true; )
{
HANDLE handles[3] = { killWorker, action1, action2 };
DWORD rc = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
switch (rc)
{
case WAIT_OBJECT_0 + 0: done = true; break;
case WAIT_OBJECT_0 + 1: doAction1(); break;
case WAIT_OBJECT_0 + 2: doAction2(); break;
default: logWarn("Unhandled wait signal");
}
}
isWorkerThreadRunning = false;
logDebug("Worker thread killed");
return 0;
}
I believe that if the worker thread receives a kill event while it is busy inside doAction1() or doAction2() the kill event won't be received and processed until doAction1() or doAction2() is completed and returned. And if doAction1() or doAction2() takes a long time to return then the worker thread will take a long time to exit.
However, I have log points sprinkled throughout doAction1() and doAction2() but I don't see any of those log points in the log file. All I see are:
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
//....many more times
Worker thead killed
which means the worker thread is not doing any work but rather waiting inside the WaitForMultipleObjects() call.
The question is why is the WaitForMultipleObjects() call sometimes take a long time (and sometimes very quick) to signal the waiter of an event??
Would changing the timeout from INFINITE to some reasonable number fix this problem?
Thanks,
Your declaration of isWorkerThreadRunning should be volatile if it is not. You can get some strange behavior when the compiler optimizes the code if it is not volatile.
volatile bool isWorkerThreadRunning;
I would also suggest entry and exit messages in your doAction functions. That will make it clearer if you're still inside one of those functions when the exit signal is sent.
Related
A snippet from my main method:
std::atomic_bool runflag;
// ...
std::thread signaller([&]() mutable {
while (runflag) {
int sig;
int rcode = sigwait(&set, &sig);
if (rcode == 0) {
switch (sig) {
case SIGINT: {
// handle ^C
}
}
}
}
});
while (runflag) {
next = cin.get();
// handle character input
}
signaller.join();
I'm using the sigwait()-based approach for detecting SIGINT sent from the command line.
The signaller thread uses sigwait() to listen for signals. The program terminates when runflag is set false. However, the signaller thread will still be blocked at sigwait when this happens. I don't think I can use condition variables, as sigwait has no way to hook into one. Is there an alternative solution that is preferably not Linux-only?
EDIT 1: Alternatively, is there an interruptible version of sigwait?
You can use the sigtimedwait() function, which returns after a timeout given as a parameter.
You will need to check the return value from sigtimedwait() to check if it finished because of timeout or the signal arrived and then depending on this value you will need to handle signal or just check runflag and run again sigtimedwait().
Here is more about it from another answer: https://stackoverflow.com/a/58834251/11424134
You can wake up the signal-handling thread by having the process send another signal to itself, eg.
kill(getpid(), SIGUSR1);
The following simple code doesn't operate as I expected. It creates a thread (suspended), starts it, waits for it to run for 1 millisecond and loops waiting until the thread dies or fails.
I expected the output to be something along the lines of:
Start
Callback running
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
... repeating for 10000 times
End
Thread end
But the output is:
Start
Callback running
Callback running
Callback running
Callback running
Callback running
... repeating for 10000 times
Callback running
End
WaitForSingleObject looping
Thread end
I thought that the wait in WaitForSingleObject would timeout at some point and interrupt the thread at some point? But the thread seems to be blocking and not asynchronous?
DWORD WINAPI callback(LPVOID param)
{
printf("Start\n");
for (int i=10000; i>0; i--)
printf("Callback running\n");
printf("End\n");
return 1;
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, callback, 0, CREATE_SUSPENDED, 0);
if (!hThread) {
printf("Failed to create thread\n");
return 0;
}
ResumeThread(hThread);
while (WaitForSingleObject(hThread, 1) == WAIT_TIMEOUT) {
printf("WaitForSingleObject looping\n");
}
CloseHandle(hThread);
printf("Thread end\n");
system("PAUSE");
return 0;
}
The dwMilliseconds parameter in WaitForSingleObject cannot be relied upon for accurate timing. The only contract is that after that much time has elapsed, the thread will eventually wake up and return the TIMEOUT value. The thread may not wake up until its next scheduled quanta, which can be as high as 60 milliseconds (or even higher on Windows Server). This is more than enough time for the second thread to complete. Try increasing the iteration count such that the worker thread takes at least one second to run - that should be plenty of time for the primary thread to be scheduled and run at least one more iteration of the TIMEOUT loop.
I'm writing a simple function that, when called, allows to execute 2 different actions (exclusive).
So there are two threads. User_choice waits until the user inserts an input and the Time_choice waits until time expires.
The choice_done shared var says that, if true, one thread has already started and blocking (it doesn't do anything!) the other one; Whereas thread_done says, if true, that thread (it doesn't matter which) has already finished, so func() waits until one thread finishes.
Here is the code.
The func procedure will be called more times during the program execution.
The various user_choice thread will be waiting forever on getline! Is it a problem? What if, after four times the program will call func() and the user doesn't insert anything, the 5th time the user inserts "yes"?
Will every user_choice thread continue the execution?? How can I kill the waiting thread? Are there other solutions?
How can I wait inside func() that a thread sets thread_done to true?
bool choice_done = false;
bool thread_done = false;
void func(){
boost::thread t1(boost::bind( time_choice() ));
boost::thread t2(boost::bind( user_choice() ));
//whait untile thread_done == true
do something...
}
// Time choice thread
void time_choice(){
sleep(5);
if(choice_done == false){
printf("Automatic choice\n");
choice_done == true;
do something...
thread_done = true;
}
}
// User choice thread
void user_choice(){
printf("Start emergency procedure?\n");
string tmp;
getline(cin, tmp);
if((tmp.compare("yes") == 0) && (choice_done == false)){
printf("Manual choice\n");
choice_done == true;
do something...
thread_done = true;
}
}
Having to create a thread for a timer is generally a sign of sub-optimal design. It does not scale well (imagine thousands of timers) and the code gets multi-threaded and more complex for no good reason. Also, sleep is not thread-safe on Linux.
Just use one thread with select and a timeout. select will wait on STDIN_FILENO for user input and timeout simultaneously.
Or, better, use a 3rd-party event-demultiplexing library, like libevent or boost::asio.
I am coding a telemetry system in C++ and have been having some difficulty syncing certain threads with the standard pthread_cond_timedwait and pthread_cond_broadcast.
The problem was that I needed some way for the function that was doing the broadcasting to know if another thread acted on the broadcast.
After some hearty searching I decided I might try using a barrier for the two threads instead. However, I still wanted the timeout functionality of the pthread_cond_timedwait.
Here is basically what I came up with: (However it feels excessive)
Listen Function: Checks for a period of milliseconds to see if an event is currently being triggered.
bool listen(uint8_t eventID, int timeout)
{
int waitCount = 0;
while(waitCount <= timeout)
{
globalEventID = eventID;
if(getUpdateFlag(eventID) == true)
{
pthread_barrier_wait(&barEvent);
return true;
}
threadSleep(); //blocks for 1 millisecond
++waitCount;
}
return false;
}
Trigger Function: Triggers an event for a period of milliseconds by setting an update flag for the triggering period
bool trigger(uint8_t eventID, int timeout)
int waitCount = 0;
while(waitCount <= timeout)
{
setUpdateFlag(eventID, true); //Sets the update flag to true
if(globalEventID == eventID)
{
pthread_barrier_wait(&barEvent);
return true;
}
threadSleep(); //blocks for 1 millisecond
++waitCount;
}
setUpdateFlag(eventID, false);
return false;
}
My questions: Is another way to share information with the broadcaster, or are barriers really the only efficient way? Also, is there another way of getting timeout functionality with barriers?
Based on your described problem:
Specifically, I am trying to let thread1 know that the message it is
waiting for has been parsed and stored in a global list by thread2,
and that thread2 can continue parsing and storing because thread1 will
now copy that message from the list ensuring that thread2 can
overwrite that message with a new version and not disrupt the
operations of thread1.
It sounds like your problem can be solved by having both threads alternately wait on the condition variable. Eg. in thread 1:
pthread_mutex_lock(&mutex);
while (!message_present)
pthread_cond_wait(&cond, &mutex);
copy_message();
message_present = 0;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
process_message();
and in thread 2:
parse_message();
pthread_mutex_lock(&mutex);
while (message_present)
pthread_cond_wait(&cond, &mutex);
store_message();
message_present = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
I spawn a thread using AfxBeginThread which is just an infinite while loop:
UINT CMyClass::ThreadProc( LPVOID param )
{
while (TRUE)
{
// do stuff
}
return 1;
}
How do I kill off this thread in my class destructor?
I think something like
UINT CMyClass::ThreadProc( LPVOID param )
{
while (m_bKillThread)
{
// do stuff
}
return 1;
}
and then set m_bKillThread to FALSE in the destructor. But I still need to wait in the destructor until the thread is dead.
Actively killing the thread:
Use the return value of AfxBeginThread (CWinThread*) to get the thread handle (m_hThread) then pass that handle to the TerminateThread Win32 API. This is not a safe way to terminate threads though, so please read on.
Waiting for the thread to finish:
Use the return value of AfxBeginThread (CWinThread*) to get the member m_hThread, then use WaitForSingleObject(p->m_hThread, INFINITE); If this function returns WAIT_OBJECT_0, then the thread is finished. Instead of INFINITE you could also put the number of milliseconds to wait before a timeout happens. In this case WAIT_TIMEOUT will be returned.
Signaling to your thread that it should end:
Before doing the WaitForSingleObject just set some kind of flag that the thread should exit. Then in your main loop of the thread you would check for that bool value and break the infinite loop. In your destructor you would set this flag then do a WaitForSingleObject.
Even better ways:
If you need even more control you can use something like boost conditions.
BTW, About TerminateThread(), use it this way.
DWORD exit_code= NULL;
if (thread != NULL)
{
GetExitCodeThread(thread->m_hThread, &exit_code);
if(exit_code == STILL_ACTIVE)
{
::TerminateThread(thread->m_hThread, 0);
CloseHandle(thread->m_hThread);
}
thread->m_hThread = NULL;
thread = NULL;
}
First you have to start the thread in a way so MFC doesn't delete the thread object when it's finished, the default setting for MFC thread is to delete itself so you want to turn that off.
m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED);
m_thread->m_bAutoDelete = FALSE;
m_thread->ResumeThread();
Now in the thread, you want a mechanism that the caller thread can send it a signal to end itself. There are multiple ways, one is the WaitForSingleObject to check the status of the signal or another way is to simply send this thread a message to end itself. This is graceful ending rather killing it.
While this thread is ending itself (= exiting the thread function, cleaning up), you can have the main thread wait on it to finish before it exits.
int wait = 2000 // seconds ( I am waiting for 2 seconds for worker to finish)
int dwRes = WaitForSingleObject( m_thread->m_hThread, wait);
switch (dwRes)
{
case WAIT_OBJECT_0:
TRACE( _T("worker thread just finished") ); break;
case WAIT_TIMEOUT:
TRACE( _T("timed out, worker thread is still busy") ); break;
}
Note setting m_bAutoDelete = FALSE above made it possible we still have a valid handle when thread finishes so we can wait on it. The last thing you want to do now is delete the CWinThread object to free its memory (since we took the responsibility to do that).
You must wait, until thread do all stuff.
if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0)
;//all right
else
;//report error
beware using TerminateThread function, this is very dangerous.