PDA

View Full Version : emit() call in QThread occasionally blocks and freezes GUI



CreeperBS
11th November 2013, 11:47
Hello everyone! :)

I am currently programming a GUI to display some results from a different C++ program using qwt plots. The results are transferred via 4 TCP links and are received in 4 QThreads. Each QThread sends the received data via a signal to a slot of the GUI to display the data in the plots. Each thread sends on average something like 5-10 signals per second. For a while everything is working fine (I am running the GUI under cygwin), but occasionally my GUI freezes. Sometimes this happens 5 minutes after starting the GUI and TCP data transfer, sometimes it happens after 2 hours. After some debugging it seems that the emit() calls block the QThreads. Interestingly, a very similar GUI programmed using exactly the same approach (but using only a single QThread) works absolutely fine. My (simplified) code looks as follows:


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

qRegisterMetaType<QSharedPointer<CPacket> >();

RodGui w;
w.show();
return a.exec();
}
Q_DECLARE_METATYPE(QSharedPointer<CPacket>)


class RodGui : public QMainWindow
{
Q_OBJECT

public:
RodGui(QWidget *parent = 0);
~RodGui();

private:
void setupAndStartNetwork();

Network* networkThreadMi;
Network* networkThreadBer;
Network* networkThreadBuffer;
Network* networkThreadQam;

//[qwt plot stuff and widgets]

private slots:
void updatePlot(QSharedPointer<CPacket> packet);
};


RodGui::RodGui(QWidget *parent) : QMainWindow(parent)
{
// [create widgets and qwt plots]
setupAndStartNetwork();
}


void RodGui::updatePlot(QSharedPointer<CPacket> packet) {
// [do some calculations with packet and update qwt plots]
}

void RodGui::setupAndStartNetwork() {

networkThreadMi = new Network(this, QString::number(20004));
networkThreadBer = new Network(this, QString::number(20005));
networkThreadBuffer = new Network(this, QString::number(20006));
networkThreadQam = new Network(this, QString::number(20007));

QObject::connect(networkThreadMi, SIGNAL(processedDatagramsReady(QSharedPointer<CPacket>)),
this, SLOT(updatePlot(QSharedPointer<CPacket>)), Qt::QueuedConnection);
QObject::connect(networkThreadBer, SIGNAL(processedDatagramsReady(QSharedPointer<CPacket>)),
this, SLOT(updatePlot(QSharedPointer<CPacket>)), Qt::QueuedConnection);
QObject::connect(networkThreadBuffer, SIGNAL(processedDatagramsReady(QSharedPointer<CPacket>)),
this, SLOT(updatePlot(QSharedPointer<CPacket>)), Qt::QueuedConnection);
QObject::connect(networkThreadQam, SIGNAL(processedDatagramsReady(QSharedPointer<CPacket>)),
this, SLOT(updatePlot(QSharedPointer<CPacket>)), Qt::QueuedConnection);

networkThreadMi->start();
networkThreadBer->start();
networkThreadBuffer->start();
networkThreadQam->start();
}


class Network : public QThread {
Q_OBJECT

public:
Network(QWidget *parent = 0, QString port = 0);

signals:
void processedDatagramsReady(QSharedPointer<CPacket>);

private:
QString port;
//[TCP stuff (boost asio)]

protected:
void run();
};

void Network::run() {

while (true) {
//[read some TCP packets via boost asio and deserialize to a class (derived from CPacket)]
qDebug() << "emit: " << port;
emit processedDatagramsReady(packet);
qDebug() << "emit complete: " << port;
}
}

When my GUI freezes the last debug output on my console looks like this:
[...]
emit: xx
emit complete: xx
emit: 20004
emit: 20005
emit: 20006
emit: 20007

So it seems that the event loop is freezing after some time, blocking the emit calls from all QThreads. Is there a problem with the approach itself? Or am I simply firing too many signals per second? Any idea what might cause this problem?

Thanks in advance!
Jan

high_flyer
11th November 2013, 17:42
maybe the reading is blocking? (the code which is NOT present - what ever is happening in the comment)

anda_skoa
11th November 2013, 19:28
Have you checked if your updatePlots slot blocks?

Cheers,
_

CreeperBS
11th November 2013, 23:25
The network connection is definitely not blocking. I guess even if it would block it wouldn't cause the GUI to freeze, since the sockets run in different QThreads.

But it indeed seems to be the case that the updatePlots() slot is blocking! I never considered that since the slot only contains some simple lines adding data to six qwt plots. But it seems that something is wrong here. No I only need to find out which qwt call blocks the slot.

Thanks for your help!