I have a threaded application in which main thread is the gui thread and the secondary thread is the one doing major computing inside nested for loops. Now the problem is how to terminate the secondary thread. When I press the stop button on the GUI thread it called a slot in the secondary thread which sets the stop variable to true. Problem with this technique is that, testing stop variable in for loops (as shown below) is not enough. Because if pressed the stop button just after thread has entered the third for loop, it will execute all lengthy functions before it will check the stop flag. Thats why we need to test it in each function before executing its contents, which I think is not not a very elegant solution.
I cannot call terminate on this thread as this thread allocates some decent amount of memory of memory and calling terminate will cause that memory to leak.
So for such a scenario what would be the best way to terminate the thread and any point?
Following code skeleton is just to give you and idea of what I/m talking about
void run( ) {
for(int i = 0; i < 4 && !stop; i++) {
for(int j = 0; j < 3 && !stop; j++) {
for(int k; k < 6 && !stop; k++) {
callA( );
callB( );
callC( );
callD( );
callE( );
callF( );
callF( );
callG( );
}
}
}
}
callA( ) { callL( ); }
callB( ) { callM( ); }
callC( ) { callN( ); }
callD( ) { callO( ); }
callE( ) { callP( ); }
callF( ) { callQ( ); }
callF( ) { callR( ); }
callG( ) { callS( ); }
callL( ) { sleep(20); }
callM( ) { sleep(60); }
callN( ) { QProcess( ); }
callO( ) { sleep(30);}
callP( ) { QProcess( ); }
callQ( ) { }
callR( ) { sleep(60); }
callS( ) { QProcess( ); }
You could call QApplication::processEvents() inside your work loop to allow the thread to receive events. An event could for instance be your main thread calling a slot setting the variable that you check to see if you should interupt your work.
//main thread calls this slot
void interupt_slot()
{
stop_was_called = true;
}
void do_work()
{
for(;;)
{
QApplication::processEvents();
if(stop_was_called)
break;
//Work
}
//Exectution is over and the thread can be stopped etc
emit its_over();
}
Edit:
It won't interupt the thread's sleep though. If the main thread invokes the interupt_slot() slot while the thread is sleeping the slot will be called when sleep(n) is over. But you could also fake sleeping by doing the work in slots that are called on a timer.
You could wrap your functions in classes and store the list of Objects of these classes in a list. So calling your functions would be in a loop iterating over this list and you will have only one code-place to check for stop condition.
By the way, in order to avoid stop-chacking in each nested loop you could use goto or throw.
In C++ leaving nested loops is the only "legal" use-case for goto.
Concerning throw, B.Stroustrup preferes it over goto and encourages to use it as a control structure.
Related
I have a class executing in a thread.
But I only want to allow it to run for 10 seconds.
Note... I have no means of passing any boolean into the class to stop execution.
So, How can I set up a thread to terminate after 10 seconds?
The class I am testing has potential infinite recursion that may take place and it is pointless to let it run longer than 10 seconds.
TEST_METHOD(TM_ClientServer_Threads)
{
bool bDone = false;
int ii = 0;
std::thread tCounter([&bDone, &ii]()
{
// Black Box: can't touch this; can't pass in a Boolean
while(true)
{
ii++;
}
}
);
std::thread tTimer([&bDone, &tCounter]()
{
Sleep(1000);
bDone = true;
// kill the tCounter thread ?
}
);
tCounter.join();
tTimer.join();
ii = ii + 0; // break point here
}
I am implementing an asynchronous log writing mechanism for my project's multithreaded application. Below is the partial code of the part where the error occurs.
void CTraceFileWriterThread::run()
{
bool fShoudIRun = shouldThreadsRun(); // Some global function which decided if operations need to stop. Not really relevant here. Assume "true" value.
while(fShoudIRun)
{
std::string nextMessage = fetchNext();
if( !nextMessage.empty() )
{
process(nextMessage);
}
else
{
fShoudIRun = shouldThreadsRun();
condVarTraceWriter.wait();
}
}
}
//This is the consumer. This is in my thread with lower priority
std::string CTraceFileWriterThread::fetchNext()
{
// When there are a lot of logs, I mean A LOT, I believe the
// control stays in this function for a long time and an other
// thread calling the "add" function is not able to acquire the lock
// since its held here.
std::string message;
if( !writeQueue.empty() )
{
writeQueueMutex.lock(); // Obj of our wrapper around pthread_mutex_lock
message = writeQueue.front();
writeQueue.pop(); // std::queue
writeQueueMutex.unLock() ;
}
return message;
}
// This is the producer and is called from multiple threads.
void CTraceFileWriterThread::add( std::string outputString ) {
if ( !outputString.empty() )
{
// crashes here while trying to acquire the lock when there are lots of
// logs in prod systems.
writeQueueMutex.lock();
const size_t writeQueueSize = writeQueue.size();
if ( writeQueueSize == maximumWriteQueueCapacity )
{
outputString.append ("\n queue full, discarding traces, traces are incomplete" );
}
if ( writeQueueSize <= maximumWriteQueueCapacity )
{
bool wasEmpty = writeQueue.empty();
writeQueue.push(outputString);
condVarTraceWriter.post(); // will be waiting in a function which calls "fetchNext"
}
writeQueueMutex.unLock();
}
int wrapperMutex::lock() {
//#[ operation lock()
int iRetval;
int iRetry = 10;
do
{
//
iRetry--;
tRfcErrno = pthread_mutex_lock (&tMutex);
if ( (tRfcErrno == EINTR) || (tRfcErrno == EAGAIN) )
{
iRetval = RFC_ERROR;
(void)sched_yield();
}
else if (tRfcErrno != EOK)
{
iRetval = RFC_ERROR;
iRetry = 0;
}
else
{
iRetval = RFC_OK;
iRetry = 0;
}
} while (iRetry > 0);
return iRetval;
//#]
}
I generated the core dump and analysed it with GDB and here are some findings
Program terminated with signal 11, Segmentation fault.
"Errno=45" at the add function where I am trying to acquire the lock. The wrapper we have around pthread_mutex_lock tries to acquire the lock for around 10 times before it gives up.
The code works fine when there are fewer logs. Also, we do not have C++11 or further and hence restricted to mutex of QNX. Any help is appreciated as I am looking at this issue for over a month with little progress. Please ask if anymore info is required.
I have a loop which calls pthread_join but the order of the loop does not match the order of thread's termination.
how can i monitor thread completion then call join?
for ( int th=0; th<sections; th++ )
{
cout<<"start joining "<<th<<endl<<flush;
result_code = pthread_join( threads[th] , (void**)&status);
cout<<th<<" join error "<<strerror(result_code)<<endl<<flush;
cout<<"Join status is "<<status<<endl<<flush;
}
This is my solution, which seems to maximize multi-threading throughput by serving the first
done thread . This solution does not depend on pthread_join loop order.
// loop & wait for the first done thread
std::bitset<Nsections> ready;
std::bitset<Nsections> done;
ready.reset();
for (unsigned b=0; b<sections; b++) ready.flip(b);
done = ready;
unsigned currIdx = 1;
int th = 0;
int th_= 0;
int stat;
while ( done.any() )
{
// main loops waiting for 1st thread to complete.
// completion is checked by global vector
// vStatus (singlton write protected)
// and not by pthread_exit returned value,
// in ordder to maximize throughput by
// post processig the first
// finished thread.
if ( (obj.vStatus).empty() ) { Sleep (5); continue; }
while ( ready.any() )
{
if ( sections == 1 ) break;
if ( !(obj.vStatus).empty() )
{
if ( currIdx <= (obj.vStatus).size() )
{
th_ = currIdx-1;
std::string s =
ready.to_string<char,std::string::traits_type,std::string::allocator_type>();
cout<<"checking "<<th_<<"\t"<<s<<"\t"
<<(ready.test(th_)?"T":"F")<<"\t"<<(obj.vStatus)[th_].retVal <<endl;
if ((obj.vStatus)[th_].retVal < 1)
{
if (ready.test(th_))
{
th=th_;
ready.reset(th);
goto retry;
}
}
}
}
Sleep (2);
} // while ready
retry:
cout<<"start joining "<<th<<endl<<flush;
result_code = pthread_join( threads[th] , (void**)&status);
switch (result_code)
{
case EDEADLK: goto retry; break;
case EINVAL:
case ESRCH:
case 0:
currIdx++;
stat = status->retVal;
free (status);
done.reset(th);
std::string s =
done.to_string<char,std::string::traits_type,std::string::allocator_type>();
cout<<"joined thread "<<th<<"\t"<<s<<"\t"
<<(done.test(th)?"T":"F")<<"\t"<<stat <<endl;
while (true)
{
auto ret=pthread_cancel ( threads[th] ) ;
if (ret == ESRCH) { netTH--; break; }
Sleep (20);
}
break;
}
How can I monitor thread completion then call join ?
By letting join detect the completion. (i.e. do nothing special)
I have a loop which calls pthread_join but the order of the loop does not match the order of thread's termination.
The order of the loop does not matter.
a) thread[main] calling thread[1].'join' will simply be suspended until thread[1] exits. After that, thread[main] will be allowed to continue with the rest of the loop.
b) When thread[2] terminates before thread[1], thread[main] calling thread[2].join simply returns immediately. Again, thread[main] continues.
c) The effort to ensure thread[1] terminates prior to thread[2] (to match the loop sequence) is a surprisingly time consuming effort, with no benefit.
Update in progress ... looking for code I thought I have already submitted.
Hy,
I'm writing my first Qt program and getting now in troubles with:
QObject::killTimer: timers cannot be stopped from another thread
QObject::startTimer: timers cannot be started from another thread
My program will communicate to a CANOpen bus for that I'm using the Canfestival Stack. The Canfestival will work with callback methods. To detects timeout in communication I setup a timer function (somehow like a watchdog). My timer package consist out of a "tmr" module, a "TimerForFWUpgrade" module and a "SingleTimer" module. The "tmr" module was originally C programmed so the static "TimerForFWUpgrade" methods will interface it. The "tmr" module will be part of a C programed Firmware update package.
The timer will work as follows. Before a message is sent I will call TMR_Set method. An then in my idle program loop with TMR_IsElapsed we check for a timer underflow. If TMR_IsElapsed I will do the errorhandling. As you see the TMR_Set method will be called continuously and restart the QTimer again and again.
The above noted errors are appearing if I start my program. Can you tell me if my concept could work? Why does this errors appear? Do I have to use additional threads (QThread) to the main thread?
Thank you
Matt
Run and Idle loop:
void run
{
// start communicate with callbacks where TMR_Set is set continously
...
while(TMR_IsElapsed(TMR_NBR_CFU) != 1);
// if TMR_IsElapsed check for errorhandling
....
}
Module tmr (interface to C program):
extern "C"
{
void TMR_Set(UINT8 tmrnbr, UINT32 time)
{
TimerForFWUpgrade::set(tmrnbr, time);
}
INT8 TMR_IsElapsed(UINT8 tmrnbr)
{
return TimerForFWUpgrade::isElapsed(tmrnbr);
}
}
Module TimerForFWUpgrade:
SingleTimer* TimerForFWUpgrade::singleTimer[NR_OF_TIMERS];
TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent)
{
for(unsigned char i = 0; i < NR_OF_TIMERS; i++)
{
singleTimer[i] = new SingleTimer(parent);
}
}
//static
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
if(tmrnbr < NR_OF_TIMERS)
{
time *= TimerForFWUpgrade::timeBase;
singleTimer[tmrnbr]->set(time);
}
}
//static
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr)
{
if(true == singleTimer[tmrnbr]->isElapsed())
{
return 1;
}
else
{
return 0;
}
}
Module SingleTimer:
SingleTimer::SingleTimer(QObject* parent) : QObject(parent),
pTime(new QTimer(this)),
myElapsed(true)
{
connect(pTime, SIGNAL(timeout()), this, SLOT(slot_setElapsed()));
pTime->setTimerType(Qt::PreciseTimer);
pTime->setSingleShot(true);
}
void SingleTimer::set(unsigned int time)
{
myElapsed = false;
pTime->start(time);
}
bool SingleTimer::isElapsed()
{
QCoreApplication::processEvents();
return myElapsed;
}
void SingleTimer::slot_setElapsed()
{
myElapsed = true;
}
Use QTimer for this purpose and make use of SIGNALS and SLOT for the purpose of starting and stopping the timer/s from different threads. You can emit the signal from any thread and catch it in the thread which created the timer to act on it.
Since you say you are new to Qt, I suggest you go through some tutorials before proceeding so that you will know what Qt has to offer and don't end up trying to reinvent the wheel. :)
VoidRealms is a good starting point.
You have this problem because the timers in the static array is created in Thread X, but started and stopped in Thread Y. This is not allowed, because Qt rely on thread affinity to timeout timers.
You can either create, start stop in the same thread or use signal and slots to trigger start and stop operations for timers. The signal and slot solution is a bit problematic Because you have n QTimer objects (Hint: how do you start the timer at position i?)
What you can do instead is create and initialize the timer at position tmrnbr in
TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
singleTimer[tmrnbr] = new SingleTimer(0);
singleTimer[tmrnbr]->set(time);
}
which is executed by the same thread.
Futhermore, you don't need a SingleTimer class. You are using Qt5, and you already have all you need at your disposal:
SingleTimer::isElapsed is really QTimer::remainingTime() == 0;
SingleTimer::set is really QTimer::setSingleShot(true); QTimer::start(time);
SingleTimer::slot_setElapsed becomes useless
ThusSingleTimer::SingleTimer becomes useless and you dont need a SingleTimer class anymore
I got the errors away after changing my timer concept. I'dont use anymore my SingleTimer module. Before the QTimer I won't let timeout and maybe because of that I run into problems. Now I have a cyclic QTimer that times out every 100ms in slot function I will then count the events. Below my working code:
TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent) : QObject(parent),
pTime(new QTimer(this))
{
connect(pTime, SIGNAL(timeout()), this, SLOT(slot_handleTimer()));
pTime->setTimerType(Qt::PreciseTimer);
pTime->start(100);
}
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
if(tmrnbr < NR_OF_TIMERS)
{
if(timeBase != 0)
{
myTimeout[tmrnbr] = time / timeBase;
}
else
{
myTimeout[tmrnbr] = 0;
}
myTimer[tmrnbr] = 0;
myElapsed[tmrnbr] = false;
myActive[tmrnbr] = true;
}
}
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr)
{
QCoreApplication::processEvents();
if(tmrnbr < NR_OF_TIMERS)
{
if(true == myElapsed[tmrnbr])
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0; // NOK
}
}
void TimerForFWUpgrade::slot_handleTimer()
{
for(UINT8 i = 0; i < NR_OF_TIMERS; i++)
{
if(myActive[i] == true)
{
myTimer[i]++;
if(myTimeout[i] < myTimer[i])
{
myTimer[i] = 0;
myElapsed[i] = true;
myActive[i] = false;
}
}
}
}
I am writing program in c++ which runs GNU readline in separate thread. When main thread is exited I need to finish the thread in which readline() function is called. The readline() function is returned only when standart input came (enter pressed).
Is there any way to send input to application or explicitly return from readline function?
Thanks in advance.
Instead of returning from main thread, call exit(errno). All other threads will be killed nastily!
Or, if you wanted to be nicer, and depending on your OS, you could send a signal to the readline thread, which would interrupt the syscall.
Or, if you wanted to be cleverer, you could run readline in async mode, using a select() loop with a timeout so that your thread never blocks in readine functions, and your thread can clean up after itself.
I experimented with this situation as well. I thought perhaps one could call close(STDIN_FILENO), which does cause readline to return on the other thread, but for some reason it leaves the terminal in a bad state (doesn't echo characters so you can't see what you're typing). However, a call to the 'reset' command will fix this, so the full alternative is:
close(STDIN_FILENO);
pthread_join(...); // or whatever to wait for thread exit
system("reset -Q"); // -Q to avoid displaying cruft
However, the final better solution I used, inspired by the other suggestions, was to override rl_getc:
rl_getc_function = getc; // stdio's getc passes
and then you can use pthread_kill() to send a signal to interrupt the getc, which returns a -1 to readline, which returns a NULL to the calling thread so you can exit cleanly instead of looping for the next input (the same as would happen if the user EOF'd by ctrl-D)
Now you can have your cake (easy blocking readlines) and eat it too (be able to stop by external event without screwing up the terminal)
C++ standard input is not designed to be thread safe. So, even if there was a method to programatically stop it from waiting input, you wouldn't be able to call it from another thread. Of course, there could be an implementation specific way to do so.
Old thread but still readline API seems not explored.
In order to interrupt readline first I disabled readline signal handlers.
Do not look at the ugly global_buffer I'm using - it's just an example
http://www.delorie.com/gnu/docs/readline/rlman_43.html
Reader Thread:
pthread_mutex_t lock;
int isBufferReady = 0;
char global_buffer[2500]; /// Assuming that reads will not be any bigger
void *reader_thread(void *arg)
{
rl_getc_function = getc;
rl_catch_signals = 0;
rl_catch_sigwinch = 0;
char *input;
while ( (input = readline( NULL )) )
{
i = strlen(input)-1;
if ( input[i] == '\0' )
return NULL;
/// Due to TAB there might be a whitespace in the end
while ( i > 0 )
{
if ( isspace(input[i]) )
{
input[i] = '\0';
}
else
{
break;
}
i--;
}
pthread_mutex_lock(&lock);
read_file_function( input, buffer );
free(input);
isBufferReady = 1;
pthread_mutex_unlock(&lock);
}
printf( "Im closed \n" );
return NULL;
}
Signal handler:
volatile int keepRunning = 1;
void SIG_handler(int signal)
{
int static sig_count = 0;
switch ( signal )
{
case SIGUSR2:
{
/// Yeah I know I should not printf in a signal handler
printf( "USR2: %d \n", sig_count++);
break;
}
default:
{
printf( " SIGHANDLE\n" );
keepRunning = 0;
break;
}
}
}
main:
int main( int argc, char *argv[] )
{
pthread_t file_reader;
{ /// Signal Handler registration
struct sigaction sigact = {{0}};
sigact.sa_handler = SIG_handler;
// sigact.sa_flags = SA_RESTART;
sigaction(SIGINT , &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGHUP, &sigact, NULL);
// sigaction(SIGUSR1, &sigact, NULL);
sigaction(SIGUSR2, &sigact, NULL);
}
pthread_create( &file_reader, NULL, reader_thread, NULL );
while(keepRunning)
{
pthread_mutex_lock(&lock);
if( !isBufferReady )
{
... fill in global_buffer according to some algorithm
}
pthread_mutex_unlock(&lock);
usleep(10);
pthread_mutex_lock(&lock);
if(isBufferReady)
isBufferReady = 0;
... some operation on the 'global_buffer' like write its contents to socket
pthread_mutex_unlock(&lock);
usleep(10);
}
signal(SIGINT, SIG_DFL);
pthread_cancel( file_reader );
pthread_join( file_reader, NULL);
pthread_mutex_destroy(&lock);
rl_cleanup_after_signal();
return 0;
}
With this (nowhere near perfect) code snippet I was able to finally interrupt readline without described prevously flakiness.
Used this code snippet for interactive debug purposes where I had prepared packets in simple text files and read-in those files with the help of readline.