QIODevice::readAll hangs
-
wrote on 5 Jul 2024, 07:20 last edited by
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!
-
wrote on 5 Jul 2024, 09:12 last edited by
@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...
-
wrote on 5 Jul 2024, 09:12 last edited by
@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?
-
@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.
-
@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.
wrote on 5 Jul 2024, 10:01 last edited by@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.
-
@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?
-
@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?
wrote on 5 Jul 2024, 11:44 last edited by Chruetli 7 May 2024, 12:01@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());
? -
@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.
-
@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());
?wrote on 5 Jul 2024, 12:12 last edited by@Chruetli said in QIODevice::readAll hangs:
Btw. what's the difference between readAll() and read(bytesAvailable());?
Timing, I imagine! :)
-
wrote on 9 Jul 2024, 07:34 last edited by
I tested it with my hardware an now it works! Thanks for helping me out!
-
10/10