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.
Related
I have the following code:
mytimer.cpp
#include "mytimer.h"
#include <QtCore>
MyTimer::MyTimer()
{
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
timer->start(1000);
}
void MyTimer::mySlot()
{
qDebug()<<"timer executed";
}
and in the main.cpp
#include <QCoreApplication>
#include "mytimer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyTimer mtimer;
qDebug()<<"DONE";
return a.exec();
}
Now the output comes as:
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
I am really confused by this. How is that we are done with our main function and still the code for the SLOT mySlot() is getting executed?
What are the important aspects to this? that I need to understand?
Also what changes occurs when I modify mytimer.cpp MyTimer() to:
MyTimer::MyTimer()
{
timer = new QTimer(this);
QEventLoop eventloop;
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
connect(timer,SIGNAL(timeout()),&eventloop,SLOT(quit()));
timer->start(1000);
eventloop.exec();
}
There is one timer executed just before DONE is printed. To Be specific the output now becomes:
timer executed
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
What caused that separate timer executed to appear above the DONE?
No - your main function is not done. It called a.exec() which will never return in your application.
a.exec() in turn processes a "message queue" which triggers all the timer events that call mySlot().
a.exec starts the event loop. It doesn't return a value until either QApplication::exit() or QApplication::quit() or all windows are closed.
What caused that separate timer executed to appear above the DONE?
The timer signals are always emitted from within the outermost event loop - because that's where the locus of control is (i.e. that's where the thread is running - it's inside Qt). Since you spun a local event loop (eventloop.exec();), that's where the timer invocation came from. As soon as that event loop was done and that exec() had returned, the MyTimer constructor had exited, DONE was printed out, and remaining timer invocations happen from the main event loop.
Generally speaking, code that nests event loops is broken, so if you ever find yourself with more than one exec() on the call stack, you're doing it wrong. There are a few notable exceptions: native dialogs on OS X require their own nested event loop due to OS X API deficiencies, and QDrag requires exec() also most likely due to platform deficiencies that require an exec() for portability, even if on some platforms it'd be unnecessary.
My current problem is with two QT threads. One of them emits a signal for starting an operation in the second thread, and afterwards wait for the result. As soon as the second thread finishes, the first thread should continue with its own operation using results from the second thread.
For letting the first thread sleep I use a QMutex and a QWaitCondition. The first thread emits a signal, and afterwards sleeps at the wait condition. But the problem is now: If the second thread somehow managed to be faster than the first thread, and emits the wakeAll()-call before the first thread enters the wait-condition, I get stuck. I could implement a waiting time, but then I am unflexible again, and if the second threads needs more time than the first thread is waiting, I have a problem again.
This problem has already been addressed here: http://woboq.com/blog/qwaitcondition-solving-unavoidable-race.html, but they decided to leave this problem unsolved. So, is there a possibility to avoid this race-condition?
Addition: I don't want to convert this function into a function of the first thread, because this specific function should be accessable from several threads at once without leading to a race condition. I.e. Thread1 should call the function in Thread2, wait til it is finished, Thread3 also wants to call the function, but is not allowed to do that, it has to wait till finish, too. If the function has finished, Thread3 can access it. (Same goes for more than only two threads).
Example function:
This function should emit the signal and afterwards wait for the wake signal:
void Spectrometer_Control::moveStepper(int steps, bool dir)
{
emit stepperMoving();
qDebug() << "From Spectrometer_Control: Stepper should move in direction " + QString::number(dir) + " from position " + QString::number(MonoPos);
int newTarget = MonoPos + ((dir == true)?(steps):(-1 * steps));
qDebug() << "New target: " + QString::number(newTarget);
emit moveStepperToTarget(steps, dir);
qDebug() << "Locking WaitMutex!";
WaitMutex->lock();
qDebug() << "Waiting for signal!";
WaitForEngine->wait(WaitMutex);
WaitMutex->unlock();
qDebug() << "Finally unlocked!";
}
And this function receives the call, and should wake every waiting function up:
void Stepper_Control_Worker::moveStepper(int steps, bool dir)
{
waitMutex->lock();
qDebug() << "Motor moved from down below!";
Stepper_Control_Worker::STP[1]->setValue((dir == true)?BlackLib::high:BlackLib::low);
usleep(50000);
Stepper_Control_Worker::STP[0]->setValue(BlackLib::low);
usleep(50000);
for(int i = 0; i < steps; i++)
{
Stepper_Control_Worker::STP[0]->setValue(BlackLib::high);
usleep(50000);
Stepper_Control_Worker::STP[0]->setValue(BlackLib::low);
}
WaitCond->wakeAll();
waitMutex->unlock();
emit StepperMoved(steps, dir);
}
The second function is a sub-member (not directly, but can only accessed via) of the class "stepper_control". The stepper-controller outer controls can be used by several functions, not only the function moveStepper from Spectrometer_Control, but for making things easier I only added one external function. But after I don't want to get my stepper confused, I wanted to restrict the access as described above.
It's probably safe to let the second thread send a signal back and move the code post wait to that slot.
class Worker1: public QObject{
Q_OBJECT
//...
signals:
void startWorking();
slots:
void answer(QVariant);
};
class Worker2: public QObject{
Q_OBJECT
//...
slots:
void startWorking();
signals:
void answer(QVariant);
};
Otherwise you need to have a variable that the second thread sets while holding the QMutex to signal the first:
thread1:
emit startWorking();
{
QMutexLocker lock(&thread2->mutex);
while(!thread2->finished){//loop guards against spurious wakeups
thread2->cond->wait(&mutex);
}
}
and thread2:
{
QMutexLocker lock(&mutex);
finished=true;
cond->wakeAll();
}
That way if thread2 is faster then thread2->finished is already true by the time thread1 arrives and the mutex protects the variable between testing it and waiting on the QWaitCondition.
Maybe Qt::BlockingQueuedConnection is what you need?
a blocking queued connection is like a queued connection, but the sender thread blocks until the event is picked up by the event loop of the thread the receiver is living in, the slot is invoked, and it returns;
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)
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.
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);