QIODevice::readAll hangs
-
Hi
(using Qt 6.5.3)
after increasing network traffic, reading from a socket results in an infinite loop.
I inherited the following code:while (threadRun) { while ((m_pDevice->bytesAvailable() == 0) && (threadRun)) { msleep(50); } if (threadRun) { msleep(20); QByteArray protoAr = m_pDevice->readAll(); processXml(protoAr); } }
and some else we have:
m_pDevice = new QTcpSocket(this);
Means we are reading XML content from a TCP socket (~4 messages per second, ~120 Bytes each) and processing it. I know that incomplete reads can occur but that's currently not (yet) a problem.
After some time we notice that the task hangs in a loop and consumes 100% CPU.
gdb
shows the following backtrace:
The implementation of
readAll
is shown here https://codebrowser.dev/qt6/qtbase/src/corelib/io/qiodevice.cpp.html#_ZN9QIODevice7readAllEv
from there we jump toread
https://codebrowser.dev/qt6/qtbase/src/corelib/io/qiodevice.cpp.html#_ZN16QIODevicePrivate4readEPcxb and finally toQRingBuffer::read
https://codebrowser.dev/qt6/qtbase/src/corelib/tools/qringbuffer.cpp.html#_ZN11QRingBuffer4readEPcxqint64 QRingBuffer::read(char *data, qint64 maxLength) { const qint64 bytesToRead = qMin(size(), maxLength); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { const qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize()); if (data) memcpy(data + readSoFar, readPointer(), bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; free(bytesToReadFromThisBlock); } return readSoFar; }
Any idea what's going wrong?
Thanks for helping!
-
@Christian-Ehrlicher : Of course you are right, but as this is a very low level routine i was reluctant to make wide changes. Nevertheless I tried it now and surprisingly little code remains. (Still have to remove
Thread
from the class name)connect(m_pDevice.get(), &QIODevice::readyRead, this, &xmlReaderThread::readData); ... void xmlReaderThread::readData() { QByteArray protoAr = m_pDevice->readAll(); processXml(protoAr); }
Looks better now?
-
Even though I know the answer but: Use signals and slots (and no need for a thread at all) - all of the above is completely unneeded with Qt...
-
@Christian-Ehrlicher : Of course you are right, but as this is a very low level routine i was reluctant to make wide changes. Nevertheless I tried it now and surprisingly little code remains. (Still have to remove
Thread
from the class name)connect(m_pDevice.get(), &QIODevice::readyRead, this, &xmlReaderThread::readData); ... void xmlReaderThread::readData() { QByteArray protoAr = m_pDevice->readAll(); processXml(protoAr); }
Looks better now?
-
@Chruetli said in QIODevice::readAll hangs:
Looks better now
Much better. But could not read out if the problem still persists. If so print out the bytesAvailable and only try to read that much bytes.
-
@Christian-Ehrlicher said in QIODevice::readAll hangs:
Much better. But could not read out if the problem still persists. If so print out the bytesAvailable and only try to read that much bytes.
Me neither... I need my hardware first to try it.
-
@Chruetli said in QIODevice::readAll hangs:
I need my hardware first to try it.
:)
I'm not aware of a bug report wrt this problem. Was m_pDevice created in the correct thread?
-
@Christian-Ehrlicher said in QIODevice::readAll hangs:
I'm not aware of a bug report wrt this problem. Was m_pDevice created in the correct thread?
Yes, at least this looks fine! Just for interest, what's the problem with this? Do you have me a pointer?
Btw. what's the difference between
readAll()
andread(bytesAvailable());
? -
@Chruetli said in QIODevice::readAll hangs:
Do you have me a pointer?
Accessing a QTcpSocket (or anything else) from different threads will not work / results in undefined behavior.
Btw. what's the difference between readAll() and read(bytesAvailable());?
Nothing in reality, just wanted to see if it makes a difference for you by any chance.
-