vfernandez
20th February 2007, 20:13
I have a GUI thread and a worker thread which reads from a socket. The worker thread uses the readyRead() signal to read input from the socket, process it and emit some signals that are connected to the GUI thread using a queued connection. The problem is the application sometimes just randomly blocks. Using gdb I've found just the exact place where it blocks and it seems to be just in the Qt code, which is quite strange. I could understand the worker thread getting blocked if there was no more available data in the socket ( although that shouldn't happen since I use QTcpSocket::canReadLine() ) but the GUI is getting blocked, thus not processing events and causing the typical efects of not repainting when it's needed.
This is the relevant code of the worker thread:
void ManagerThread::run()
{
m_mutex.lock();
QString hostName = m_hostName;
quint16 port = m_port;
m_mutex.unlock();
m_socket = new QTcpSocket;
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(handleConnectionError(QAbstractSocket::Socket Error)));
m_socket->connectToHost(hostName, port);
if (!m_socket->waitForConnected()) {
delete m_socket;
return;
}
if(sendLogin()) {
connect(m_socket, SIGNAL(readyRead()),
this, SLOT(readInput()));
setConnected(true);
emit connected();
exec();
setConnected(false);
}
m_socket->disconnectFromHost();
delete m_socket;
}
void ManagerThread::readInput()
{
bool timerStarted = false;
while(m_socket->canReadLine()) {
QString line = m_socket->readLine();
line.remove('\r');
line.remove('\n');
if(line.isEmpty()) {
m_pendingCommands.append(m_currentCommand);
m_currentCommand.clear();
if(!timerStarted) {
QTimer::singleShot(0, this, SLOT(parsePendingCommands()));
timerStarted = true;
}
} else
m_currentCommand.append(line);
}
}
It hangs in the m_socket->readLine() call. When it hangs, I press Ctrl+C and this is the backtrace I get:
(gdb) run
Starting program: /home/djworld/curro/dialapplet/dialapplet/bin/dialapplet
Failed to read a valid object file image from memory.
[Thread debugging using libthread_db enabled]
[New Thread -1224792368 (LWP 10926)]
Qt: gdb: -nograb added to command-line options.
Use the -dograb option to enforce grabbing.
[New Thread -1228108912 (LWP 10929)]
[New Thread -1236501616 (LWP 10930)]
[New Thread -1248855152 (LWP 12367)]
Program received signal SIGINT, Interrupt.
[Switching to Thread -1224792368 (LWP 10926)]
0xb7463b06 in QRingBuffer::readPointer (this=0x80e8694)
at ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:54
54 ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:
File or directory doesn't exist.
in ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h
(gdb) bt
#0 0xb7463b06 in QRingBuffer::readPointer (this=0x80e8694)
at ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:54
#1 0xb7475494 in QAbstractSocket::readData (this=0x8164370,
data=0x81f6418 "_madrugada\nQueue: Cola_madrugLocation:
SIP/101\naMembership:Penalty: 0\n stCallsTaken: LastCall: Status: 6\nPEvent:
QueueMemberStaPrivilege: aQueue: Cola\ngent,aMembership:CallsTaken:
26\ntic\nl\nStatus: 6\nP"..., maxSize=16384) at qabstractsocket.cpp:1699
#2 0xb732701a in QIODevice::read (this=0x8164370, data=0xbf9e8d2a "\236�I ",
maxSize=1) at io/qiodevice.cpp:768
#3 0xb73183d6 in QIODevice::getChar (this=0x8164370, c=0xbf9e8d77 "\b")
at ../../include/QtCore/../../src/corelib/io/qiodevice.h:116
#4 0xb7327590 in QIODevice::readLineData (this=0x8164370,
data=0x81d5570 "0\024Y]\001", maxSize=4063) at io/qiodevice.cpp:1112
#5 0xb74751f8 in QAbstractSocket::readLineData (this=0x8164370,
data=0x81d5570 "0\024Y]\001", maxlen=4063) at qabstractsocket.cpp:1719
#6 0xb732689d in QIODevice::readLine (this=0x8164370, data=0x81d5550 "Event:
QueueMemberStaPrivilege: 0\024Y]\001", maxSize=4095) at io/qiodevice.cpp:1013
#7 0xb7326b10 in QIODevice::readLine (this=0x8164370, maxSize=0) at
io/qiodevice.cpp:1081
#8 0x08052e01 in ManagerThread::readInput (this=0x8141408) at
managerthread.cpp:103
#9 0x08073bfd in ManagerThread::qt_metacall (this=0x8141408,
_c=QMetaObject::InvokeMetaMethod, _id=8, _a=0xb5900648) at
moc_managerthread.cpp:95
#10 0xb7399b2a in QObject::event (this=0x8141408, e=0xb5900668) at
kernel/qobject.cpp:1025
#11 0xb77ed7e1 in QApplicationPrivate::notify_helper (this=0x8095278,
receiver=0x8141408, e=0xb5900668) at kernel/qapplication.cpp:3434
#12 0xb77edada in QApplication::notify (this=0xbf9e9774, receiver=0x8141408,
e=0xb5900668) at kernel/qapplication.cpp:3009
#13 0xb738936b in QCoreApplication::sendEvent (receiver=0x8141408,
event=0xb5900668) at kernel/qcoreapplication.h:183
#14 0xb7386ce0 in QCoreApplication::sendPostedEvents (receiver=0x0,
event_type=0) at kernel/qcoreapplication.cpp:1021
#15 0xb7888f20 in QCoreApplication::sendPostedEvents ()
at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:188
#16 0xb788837e in QEventDispatcherX11::processEvents (this=0x809ca00,
flags=@0xbf9e95ac) at kernel/qeventdispatcher_x11.cpp:55
#17 0xb7383f06 in QEventLoop::processEvents (this=0xbf9e963c,
flags=@0xbf9e95f0) at kernel/qeventloop.cpp:126
#18 0xb7384089 in QEventLoop::exec (this=0xbf9e963c, flags=@0xbf9e9644) at
kernel/qeventloop.cpp:172
#19 0xb73875b0 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:727
#20 0xb77ed364 in QApplication::exec () at kernel/qapplication.cpp:2927
#21 0x0806138c in main (argc=Cannot access memory at address 0x0
) at main.cpp:50
Any idea? I'm using Qt 4.2.2 on openSUSE 10.2.
This is the relevant code of the worker thread:
void ManagerThread::run()
{
m_mutex.lock();
QString hostName = m_hostName;
quint16 port = m_port;
m_mutex.unlock();
m_socket = new QTcpSocket;
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(handleConnectionError(QAbstractSocket::Socket Error)));
m_socket->connectToHost(hostName, port);
if (!m_socket->waitForConnected()) {
delete m_socket;
return;
}
if(sendLogin()) {
connect(m_socket, SIGNAL(readyRead()),
this, SLOT(readInput()));
setConnected(true);
emit connected();
exec();
setConnected(false);
}
m_socket->disconnectFromHost();
delete m_socket;
}
void ManagerThread::readInput()
{
bool timerStarted = false;
while(m_socket->canReadLine()) {
QString line = m_socket->readLine();
line.remove('\r');
line.remove('\n');
if(line.isEmpty()) {
m_pendingCommands.append(m_currentCommand);
m_currentCommand.clear();
if(!timerStarted) {
QTimer::singleShot(0, this, SLOT(parsePendingCommands()));
timerStarted = true;
}
} else
m_currentCommand.append(line);
}
}
It hangs in the m_socket->readLine() call. When it hangs, I press Ctrl+C and this is the backtrace I get:
(gdb) run
Starting program: /home/djworld/curro/dialapplet/dialapplet/bin/dialapplet
Failed to read a valid object file image from memory.
[Thread debugging using libthread_db enabled]
[New Thread -1224792368 (LWP 10926)]
Qt: gdb: -nograb added to command-line options.
Use the -dograb option to enforce grabbing.
[New Thread -1228108912 (LWP 10929)]
[New Thread -1236501616 (LWP 10930)]
[New Thread -1248855152 (LWP 12367)]
Program received signal SIGINT, Interrupt.
[Switching to Thread -1224792368 (LWP 10926)]
0xb7463b06 in QRingBuffer::readPointer (this=0x80e8694)
at ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:54
54 ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:
File or directory doesn't exist.
in ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h
(gdb) bt
#0 0xb7463b06 in QRingBuffer::readPointer (this=0x80e8694)
at ../../include/QtCore/private/../../../src/corelib/tools/qringbuffer_p.h:54
#1 0xb7475494 in QAbstractSocket::readData (this=0x8164370,
data=0x81f6418 "_madrugada\nQueue: Cola_madrugLocation:
SIP/101\naMembership:Penalty: 0\n stCallsTaken: LastCall: Status: 6\nPEvent:
QueueMemberStaPrivilege: aQueue: Cola\ngent,aMembership:CallsTaken:
26\ntic\nl\nStatus: 6\nP"..., maxSize=16384) at qabstractsocket.cpp:1699
#2 0xb732701a in QIODevice::read (this=0x8164370, data=0xbf9e8d2a "\236�I ",
maxSize=1) at io/qiodevice.cpp:768
#3 0xb73183d6 in QIODevice::getChar (this=0x8164370, c=0xbf9e8d77 "\b")
at ../../include/QtCore/../../src/corelib/io/qiodevice.h:116
#4 0xb7327590 in QIODevice::readLineData (this=0x8164370,
data=0x81d5570 "0\024Y]\001", maxSize=4063) at io/qiodevice.cpp:1112
#5 0xb74751f8 in QAbstractSocket::readLineData (this=0x8164370,
data=0x81d5570 "0\024Y]\001", maxlen=4063) at qabstractsocket.cpp:1719
#6 0xb732689d in QIODevice::readLine (this=0x8164370, data=0x81d5550 "Event:
QueueMemberStaPrivilege: 0\024Y]\001", maxSize=4095) at io/qiodevice.cpp:1013
#7 0xb7326b10 in QIODevice::readLine (this=0x8164370, maxSize=0) at
io/qiodevice.cpp:1081
#8 0x08052e01 in ManagerThread::readInput (this=0x8141408) at
managerthread.cpp:103
#9 0x08073bfd in ManagerThread::qt_metacall (this=0x8141408,
_c=QMetaObject::InvokeMetaMethod, _id=8, _a=0xb5900648) at
moc_managerthread.cpp:95
#10 0xb7399b2a in QObject::event (this=0x8141408, e=0xb5900668) at
kernel/qobject.cpp:1025
#11 0xb77ed7e1 in QApplicationPrivate::notify_helper (this=0x8095278,
receiver=0x8141408, e=0xb5900668) at kernel/qapplication.cpp:3434
#12 0xb77edada in QApplication::notify (this=0xbf9e9774, receiver=0x8141408,
e=0xb5900668) at kernel/qapplication.cpp:3009
#13 0xb738936b in QCoreApplication::sendEvent (receiver=0x8141408,
event=0xb5900668) at kernel/qcoreapplication.h:183
#14 0xb7386ce0 in QCoreApplication::sendPostedEvents (receiver=0x0,
event_type=0) at kernel/qcoreapplication.cpp:1021
#15 0xb7888f20 in QCoreApplication::sendPostedEvents ()
at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:188
#16 0xb788837e in QEventDispatcherX11::processEvents (this=0x809ca00,
flags=@0xbf9e95ac) at kernel/qeventdispatcher_x11.cpp:55
#17 0xb7383f06 in QEventLoop::processEvents (this=0xbf9e963c,
flags=@0xbf9e95f0) at kernel/qeventloop.cpp:126
#18 0xb7384089 in QEventLoop::exec (this=0xbf9e963c, flags=@0xbf9e9644) at
kernel/qeventloop.cpp:172
#19 0xb73875b0 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:727
#20 0xb77ed364 in QApplication::exec () at kernel/qapplication.cpp:2927
#21 0x0806138c in main (argc=Cannot access memory at address 0x0
) at main.cpp:50
Any idea? I'm using Qt 4.2.2 on openSUSE 10.2.