std::thread consumes all CPUs in Qt - c++

I have a function. In my function there is a c++ thread & a Qtimer. By c++ thread I receive ARP Reply packets & by QTimer I send ARP Request packets.
The simplified structure:
int foo()
{
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
std::thread tCapture(Capture);
tCapture.join();
return 0;
}
void Capture()
{
while ( ! finishCapturing )
{
do sth
}
}
In the tCapture thread I have a while loop that consumes all CPUs & the Qtimer does not work!
I use .join() because I want to wait for the thread to finish.
when I set finishCapturing flag in Qtimer slot, the thread will be finished.
The above codes don't work correctly, because the c++ thread consumes all CPUs!
what is the problem?
Thanks a lot.
Ya Ali.

The problem is joining the thread right after creating them, that blocks the GUI thread and the QTimer and all slots on that thread.
What you should do is emit a signal when capturing is done;
public void beginSending(){
//do sending and capture
finishCapturing =true;
emit finshedCapture();
}
If needed you can put the body of the while in a slot and have it called repeatedly with a QTimer with a timeout of 0 (which means the slot will get called as often as possible).
then you can connect the finshedCapture() signal to the stop() slot of the QTimer
int foo()
{
... some codes ...
QTimer::singleShot(1000, this, SLOT(beginSending()));
QTimer* timer = new QTimer(this);
connect(timer, signal(timeout()), this, slot(Capture()));
connect(this, signal(finshedCapture()), timer, slot(stop()));
connect(this, signal(finshedCapture()), timer, slot(deleteLater()));//cleaup when done
timer->setTimeout(0);
timer->setSingleShot(false);
timer->start();
return 0;
}
void Capture()
{
//no while because the timer will call it as needed
//do sth
}

Without seeing more of the code, this is guess-work:
1: Capture() does not block, so will consume as much CPU time as the operating system gives it - which will be 100% of one CPU on a lightly loaded multi-core system.
2: foo() is called on the main thread. It then attempts to join() with the your thread - which blocks until the thread finished. I see nothing setting finishCapturing, so it doesn't.
3: The QTimer is dispatched through the run-loop - which is blocked.
In effect, this is deadlock of the main thread.

Related

Qthread deleteLater() crashing program

QT 4.8: I have been getting a number of segment faults and I/O Possible errors in my code that I cannot figure out. From print statements I have seen a number of odd and inconsistent behaviors, likely indicating race conditions. Many times everything works perfect. Sometimes I get an I/O error immediately after the worker destructor is called, indicating main connect deleteLater() issue. Other times if I try to delete audioOutput in destructor it will work a number of times then give me a segment fault (or I/O) randomly in middle of destructor on other attempts. I believe my issues can be attributed to 2 things, worker cleanup/ connect quit()/deletelater() calls and my recursive loop in worker which needs to create its own event loop every time thus possibly emitting finished signal before the previous calls can be cleaned up?
Specifically my questions are:
What could cause deleteLater() to create an I/O Possible error?
how should I delete pointers inside of worker class so they are deleted at the correct time (end)... or does QT handle this for me?
Gui and .h
QByteArray* qbyte;
QThread* thread;
PlayAudio* audioWorker;
MainWindow::startSound()
{
QFile soundFile;
soundFile.setFileName("/home/sounds/sound.wav");
qbyte = new QByteArray(soundFile.readAll());
soundFile.close();
thread= new QThread;
audioWorker= new PlayAudio(qbyte, 5);
audioWorker->moveToThread(thread);
connect(thread, SIGNAL(started()), audioWorker, SLOT(play()));
connect(audioWorker, SIGNAL(finished()), thread, SLOT(quit()));
connect(audioWorker, SIGNAL(finished()), audioWorker,SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), this, SLOT(donePlaying()));
}
MainWindow::donePlaying()
{
//do stuff
}
Worker class and .h
QByteArray qbyte;
int numOfPlays;
int numOfPlaysRun;
bool quit = false;
QBuffer *qbuff;
QAudioFormat format;
QAudioOutput *audioOutput;
PlayAudio::PlayAudio(QByteArray *qbyte_, int num)
{
qbyte=*qbyte_;
numOfPlays=num;
qbuff=new QBuffer();
qbuff->setData(qbyte);
qbuff->open(QIODevice::ReadOnly);
//set format
audioOutput = new QAudioOutput(format,this);
connect(audioOutput,SIGNAL(stateChanged(QAudio::State)),
SLOT(finishedPlaying(QAudio::State)));
}
void PlayAudio::::play()
{
if (!quit)
{
audioOutput->start(qbuff);
QEventLoop loop;
do {
loop.exec();
} while(!quit);
}
}
void PlayAudio::finishedPlaying(QAudio::State state)
{
if (state == QAudio::IdleState)
{
if (numOfPlaysRun< numOfPlays && !quit)
{
numOfPlaysRun++;
play();
}
else
{
//should i ever stop loop myself? or is that done from main?
//quit=true;
emit finished();
}
}
}
PlayAudio:: ~PlayAudio()
{
// still have qbuff and audioOutput to delete. If i do here i sometimes
//get segment faults or IO error.
}
updated:
still have intermittent issues but commenting out the following line has helped clear some of them in combination with setting quit=true.
connect(audioWorker, SIGNAL(finished()), audioWorker,SLOT(deleteLater()));
But this may cause a memory leak?
Update 2:
I'm starting to think I'm talking to myself here but I think I got it. It appears this was a timing issue as the thread was returning finished() prior to the worker actually finishing due to the time to unwind from quit() signal that closes the open loops once the worker emits finished(). So I now emit a custom signal from worker for every loop closed and track this in main. Once I receive what I expect I then release wait() and delete the thread THEN then worker. Not sure if this is correct but it seems to be working. Seems hackish to me but IMO the thread shouldn't return finished until the worker does, seems pointless then. but oh well.

Start QTimer from another non-gui thread

I try to start QTimer from another thread ( to get better accuracy ).
I think that problem is with function connect but let see my code:
//code from constructor of parent.cpp class
{
//run_clock_timer(this); // this works
std::thread t1{ [this] { run_clock_timer(this); } }; //not works
t1.join();
}
And function:
void class::run_clock_timer(class* inst){
QTimer * test = new QTimer(inst);
connect(test, SIGNAL(timeout()), inst, SLOT(updateTime()));
test->setInterval(50);
test->start(timer_precision);
}
Debugger told me that code from run_clock_timer was run, but no result.
I think i will do it with no problem when i use QThread, but i want to use std::thread.
So whats wrong with my function ?
The problem is that QTimer depends on the ability to interact with a running Qt event loop in order to perform its task. Since a non-Qt thread has no event loop, the QTimer can't do its job. (i.e. there has to be some Qt code running in the thread, that will emit the timeout() signal, that doesn't just happen on its own)

Qt: QFuture/QtConcurrent timeout function call

I need a timeout function call. I work mainly with Qt (4.7.3, 4.8.5) and so i tried to find a solution with Qt. The two classes QFuture and QtConcurrent seems to do 99% of what i need but i can not find a possibility to timeout a function call.
My Problem:
I have my tester (gtest) and i test a function which can end in an infinity loop => so i want to test this to fix that problem[s] (this function is internal extrem complex :-( ). I want to add a timeout-time to break out if there is an infinity loop => so i can tell the tester that something is wrong (infinity loop) and i will terminate the thread.
I have search for something like that:
QtConcurrent::run(............,30000 /*30 seconds timeout)*/;
Does anybody know how i can do this?
(If it is possible with native C++, or boost, or ... you can also tell me your solution)
I was focusing on the QtConcurrent module, since you mentioned it in your question. But you can achieve your goal also with plain QThread:
// A Thread calling your test function
class MyThread : public QThread {
protected:
void run() { myFunction(); }
};
// calling the function
MyThread t;
t.start();
if ( t.wait(30000) ) {
// Finished
} else {
// Not finished
// ATTENTION: USE TERMINATE WITH CARE (see QThread documentation)!
t.terminate();
}
The call to terminate will forceably stop the thread and thus stop the execution of your function. Note however that the thread cannot cleanup, and any resources used by your function are not freed properly.
Old Answer:
You can do this with Qt, using a QFutureWatcher, a QTimer, and a helper QEventLoop . Setup your concurrent run, and watch the result with the watcher. Set the Timout with the timer, and wait until either is finished, in a Event loop.
// Setup eventloop, watcher and timer
QEventLoop loop;
QFutureWatcher watcher;
QObject::connect( &watcher, SIGNAL(finished()), &loop, SLOT(quit()));
QTimer::singleShot( 30000, &loop, SLOT(quit()) );
// Start function call
QFuture<T> future = QtConcurrent::run(...);
// Watch the call
watcher.setFuture( future );
// Wait until event loop finishes
loop.exec();
// Now either future has finished, or timeout was reached...
if ( future.isFinished() ) {
// Function completed!
} else {
future.cancel();
// Infinite loop...
}
The issue is that you cannot safely terminate a thread without thread's cooperation. The thread may be accessing some shared data structure, like the C-runtime heap, and if it is terminated forcefully then such data structures will remain in a mid-change state, essentially corrupted. Any future access to them from within the program will likely cause a crash or worse.
The case of an infinite loop is not by any means different from other bad scenarios. What if the function you launch crashes the program, how do you report it to the tester?
In your case you simply don't trust the code that you're executing. The solution is to launch it in a separate process, whose safe termination is guaranteed by the operating system. By isolating the tested code from the tester application you guarantee that you can detect all kind of problems, including timeouts or abnormal termination.
I think you need to find out why the infinite loop happens rather than trying to fix symptoms.
QtConcurrent::run() uses thread pool to run tasks. You can't safely terminate thread, so the only way to safely finish a task is to return from it.
If you still want timeouts, you can add something like this to your function with loop:
QTime t;
t.start();
// it's your loop
while( true ) {
if( t.elapsed() > 30*1000 ) {
return 1;
}
...
}
You can bind a QTimer signal to the slot:
auto process = QtConcurrent::run(...);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &process]() {
process.cancel();
});
timer->start(3000);
Edit: As the cancel() method won't work on the QtConcurrent::run function, the easiest thing would be to use some kind of isRunning flag:
bool isRunning = true;
void runnable() {
while (isRunning) {
...
}
}
auto process = QtConcurrent::run(runnable);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &isRunning]() {
isRunning = false;
});
timer->start(3000);

Unable to connect between QThread with finished() signal for multiple Qthread

I have a 3 QThreads invoking by one another (all inherited from QThread. I know some might suggest to use moveToThread, but just ignore this fact for now). The simplified code looks like following:
Thread1 class:
void
Thread1::run
{
// some execution
Thread2 t2 = new Thread2();
connect(t2,SIGNAL(finished),this,SLOT(onFinished));
t2->start();
while(!stop) // stop was initialized as false
{
this->msleep(10);
}
}
void Thread1::onFinished(){ stop = true; }
Thread2 class:
void
Thread2::run
{
// some execution
Thread3 t3 = new Thread3();
connect(t3,SIGNAL(finished),this,SLOT(onFinished));
t3->start();
while(!stop) // stop was initialized as false
{
this->msleep(10);
}
}
void Thread2::onFinished(){ stop = true; }
Thread3 class:
void
Thread3::run
{
// some execution
QMutexLocker ml(&mMutex);
}
When I have only two threads, it works perfectly fine (e.g. just thread2 and thread3). The onFinished() method seems not connecting with finished() signal properly anymore, after I moved to a three-threads scenario. The onFinished() in thread2 has ever been called. And I am pretty sure the execution of the thread3 has completed.
Can anybody tell me where I could have done wrong?
First of all you should note that the default connection type is Qt::AutoConnection. This means if signal is emitted from a different thread than the receiving object's thread, Qt::QueuedConnection is used. In this case: The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. So you need an event loop.
It works with 2 threads because you probably have an event loop running in your main thread. In your case where you use only thread2 and thread3 objects, thread2 object will actually live in the main thread, while thread3 object will live in the thread managed by the thread2 object. So slots in thread2 object should work.
But in the case of 3 threads, thread1 object would live in the main thread, thread2 object would live in the thread managed by thread1 object, and because there is no running event loop there, the slot in thread2 object will never be executed.
You can call QThread::exec() in your QThread::run() function, but note that the slots will be executed in the thread where your QThread object lives in, not the thread it manages. Because of this you shouldn't use slots in QThread subclasses. You should create a QObject subclass and move it to a thread.
Another option is to use Qt::DirectConnection for the connection type, when you connect your signals to slots.

qt signal-slot multithreading deadlocks

In my code a worker thread emits a signal to gui thread. Signal and Slot are connected via Qt::BlockingQueuedConnection.
When during thecloseEvent application is trying to stop the worker thread and only then finishes the event.
It calls the function of worker thread:
void stop() {
_isFinished = true;
wait();
}
The worker thread in its turn checks _isFinished condition and if it is not set up then emit the signal.
Imaging the following situation
The worker Gui Thread
================= =================
if (!_isFinished) -----------------
----------------- _isFinished = true;
----------------- wait();
emit mySignal(); -----------------
Evidently, both threads would be locked - deadlock.
If I add a mutex then you can find another deadlock situation. When the worker locks the mutex and the gui thread would be blocked. As a result the emitted signal will lock the worker.
How can I deal with this?
This is how I see the situation.
In your main thread you do not need to wait for worker to quit. Instead your closeEvent should look like this:
if (workerThread->isRunning())
{
workerThread->stop();
event->ignore();
}
To make this work, you also need to close main window, when worker thread finishes:
connect(workerThread, SIGNAL(finished()), SLOT(close()));
Finally, all manipulations with _isFinished (and all other variables in worker thread) should occur in worker thread. You can achieve it with a simple trick:
WorkerThread.h
public:
void stop();
protected slots:
void p_stop();
protected:
QMutex mutex;
WorkerThread.cpp
void WorkerThread::stop()
{
staticMetaObject.invokeMethod(this, "p_stop", Qt::QueuedConnection);
}
void WorkerThread::p_stop();
{
QMutexLocker locker(&mutex);
_isFinished = true;
}
This way you can avoid deadlocks.
In the gui thread you can use QEventLoop for wait. Look like this:
void stop() {
QEventLoop eventloop;
connect(&theWorkerThread, &QThread::finished, &eventloop, QEventLoop::quit);
_isFinished = true;
eventloop.exe();
}