PDA

View Full Version : QThread issues. Crash after 2058 runs.



zverj
14th October 2009, 13:53
Following thread code runs 2058 times, after that it crashes. Can somebody help me figure out why? The idea of the program is create some class in main thread, pass it to worker thread, thread fills needed data and pass data back to main thread. This example crashes after 2058 runs, however it should go indefinately. I've run it 20 times, i've tried several computers, always the same number. In version of reduced qWarning() calls (print simple line each 100 runs) thread gets executed 3000 times. So I guess it does not depend on amount of qWarning() calls. And why pointer address for SharedData *d is always the same?

main.cpp



int main(int argc, char *argv[])
{
QApplication a(argc, argv);

TestThread* thread = new TestThread();

MainWindow w(thread);
w.show();

return a.exec();
}

mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include <QThread>
#include <QHash>

class SharedData
{
public:
SharedData();
QString var;
QHash<QString, QString> hash;
};

class TestThread : public QThread
{
Q_OBJECT

public:
TestThread(QObject *parent = 0);
void doWork(SharedData* _data);
void doCrash(QHash<QString, QString>* hash);
signals:
void completed(SharedData* d);
private:
SharedData* data;
protected:
void run();
};

namespace Ui
{
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(TestThread* t, QWidget *parent = 0);
~MainWindow();
void runThread();
public slots:
void jobDone(SharedData* req);

private:
Ui::MainWindow *ui;
TestThread* t;
int runcount;
};

#endif // MAINWINDOW_H


mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug.h>

TestThread::TestThread(QObject *parent) : QThread(parent)
{
}

void TestThread::run()
{
qWarning() << "Thread running";
data->var = "hello";
doCrash(&data->hash);
emit completed(data);
}

void TestThread::doWork(SharedData* _data)
{
data = _data;
qWarning() << "Attempting to start";
if(!isRunning())
{
run();
}
else
{
qWarning() << "Oops. Already running";
}
}

void TestThread::doCrash(QHash<QString, QString>* hash)
{
hash->insert("test", "123");

/*
QHashIterator<QString, QString> i(*hash);
while (i.hasNext()) {
i.next();
qWarning() << i.key() + ":" + i.value();
}
*/
}

SharedData::SharedData()
{
}

void MainWindow::jobDone(SharedData* req)
{
qWarning() << "RETURNED";
qWarning() << "var: " << req->var << " addr: " << &req->var;
qWarning() << "cnt: " << req->hash.count() << " addr: " << &req->hash;

QHashIterator<QString, QString> i(req->hash);

while (i.hasNext()) {
i.next();
qWarning() << i.key() + ":" + i.value();
}

delete req;
runThread();
}

MainWindow::MainWindow(TestThread* _t, QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);

t = _t;
connect(t, SIGNAL(completed(SharedData*)), this, SLOT(jobDone(SharedData*)));
runcount = 0;
runThread();
}

void MainWindow::runThread()
{
SharedData* d = new SharedData();
d->var = "test";

runcount++;
qWarning() << "Run count: " << runcount;

qWarning() << "CREATING THREAD";
qWarning() << "var: " << d->var << " addr: " << &d->var;
qWarning() << "cnt: " << d->hash.count() << " addr: " << &d->hash;

t->doWork(d);
}

MainWindow::~MainWindow()
{
delete ui;
}

tsp
14th October 2009, 18:24
Your code seems to be endless loop, your call sequence goes something like:



:
:
-> runThread
-> doWork
-> run
-> emits completed (connected to jobDone)
-> jobDone
-> runThread
-> doWork
:
:

Maybe because of this you reach some system resource limit (heap/stack) in this recursive function call sequence and that causes your code to crash at the point you mentioned.

I have 8GB RAM in Ubuntu and I reach ~9500 (runcount) after crash, at that point my function call "tree" is 66609 function deep!

zverj
15th October 2009, 09:15
Your code seems to be endless loop, your call sequence goes something like:

Maybe because of this you reach some system resource limit (heap/stack) in this recursive function call sequence and that causes your code to crash at the point you mentioned.

I have 8GB RAM in Ubuntu and I reach ~9500 (runcount) after crash, at that point my function call "tree" is 66609 function deep!

It is intended to be ENDLESS. However it is not and I want to find out why.

faldzip
15th October 2009, 09:53
when it is intended to be endless it cannot be recursive (I did not investigate your code carefully but tsb might be right), because it will fill up your stack which ends in stack overflow error. And I think this happens in you case because I don't think that calling run() starts new thread (in docs in says that start() method is for starting thread which execute run() method in new thread - in OS meaning) and your emit expands to function call so it is endless recursion which requires endless stack size so it implies that you have to have endless amount of RAM. So buy some more RAM to extend life time of your app :P

tsp
15th October 2009, 11:13
It is intended to be ENDLESS. However it is not and I want to find out why.

It is endless loop to the point where you run out of system resources. Please check the traces I posted above and you see the recursion, that is the problem in your code!