Qt Message, what does it mean, is it important ?
-
In my debug file which I report various bits of information which includes warnings, errors, fatal errors and information. When I launch my application I see at the end of the file and always at the end of the file:
S000000000030E000000001009T15:55:41.939W:QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x60000002de00), parent's thread is clsServer(0x600000278700), current thread is clsThread(0x600002c50800) S000000000031E000000002603T15:55:43.532W:QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x60000000e720), parent's thread is clsServer(0x6000002642e0), current thread is clsThread(0x600002c50800) S000000000032E000000002647T15:55:43.577W:QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0x600000020160), parent's thread is clsServer(0x600000260cc0), current thread is clsThread(0x600002c50800)
The bit before the message is my own information which I prefix all messages with:
S000000000030E000000001009T15:55:41.939W:
This is the code that constructs the output:
QString strPrefix(QString("S%1E%2T%3") .arg(cint64NextStep, cintSeqNoLength, cintSeqNoBase, QChar('0')) .arg(cint64ElapsedTime, cintTimeLength, cintTimeBase, QChar('0')) .arg(cstrtimeNow));
The question is are these messages significant and are they anything to worry about? I assume because its always at the end that something is happening when I stop the application, as I'm still in development this usually is a stop from Qt Creator.
-
@SPlatten said in Qt Message, what does it mean, is it important ?:
The question is are these messages significant and are they anything to worry about? I
Cannot create children for a parent that is in a different thread.
I mean - do they look as you can ignore them?
You do something wrong in your threading code - fix it. -
@Christian-Ehrlicher Agree. I will be worried.
-
@Christian-Ehrlicher , @JoeCFD , not terribly helpful. These are added to the log file when the application is started, not as I originally said when it is terminated, there are just three that go into the log file, no more no less.
These are the classes mentioned in the reported messages, prototypes:
/** * File: clsListener.h * Notes: This file contains the prototypes for the classes: * clsServer and clsListener ******************************************************************************* * Class: clsServer * Inherits: QThread * * Members: * msckDescriptor Socket descriptor * mpsckIncoming Pointer to incoming socket * * Methods: * clsServer Class constructor * ~clsServer Class destructor * run Thread loop * * Signals: * error Signal emitted when error occurs * * Slots: * cleanup Cleanup socket * onDisconnected Slot connected to QAbstractSocket::disconnected * onErrorOccurred Slot connected to QAbstractSocket::errorOccurrred * onReadyRead Slot connected to QAbstractSocket::readyRead ******************************************************************************* * Class: clsListener * Inherits: QTcpServer * * Static Methods: * commonDecode Common JSON decode * pGetListener Access method to get listener for IP port * uint16NextPort Get next port * * Static Members: * msmpListeners Map of listeners * msuint16NextPort Next available port * * Members: * mpServer Pointer to instance of QTcpServer * muint16Port Port assigned to listener * * Methods: * clsListener Class constructor * ~clsListener Class destructor * uint16Port Access method to get port * * Slots: * onAcceptError Slot to accept socket error * onNewConnection Slot to accept new connection ******************************************************************************* * History: 2020/11/30 Created by Simon Platten */ #ifndef CLSLISTENER_H #define CLSLISTENER_H #include <map> #include <QAbstractSocket> #include <QDataStream> #include <QJsonDocument> #include <QJsonObject> #include <QQueue> #include <QTcpServer> #include <QTcpSocket> #include <QThread> class clsListener; typedef std::map<quint16, clsListener*> mpListeners; #if !defined(mqueJSON) typedef QQueue<QJsonObject> mqueJSON; #endif class clsServer : public QThread { Q_OBJECT private: qintptr msckDescriptor; QTcpSocket* mpsckIncoming; public: explicit clsServer(qintptr sckDescriptor, QObject* pParent = nullptr); ~clsServer(); void run(); signals: void error(QTcpSocket::SocketError socketerror); public slots: void cleanup(); void onDisconnected(); void onErrorOccurred(QAbstractSocket::SocketError error); void onReadyRead(); }; class clsListener : public QTcpServer { Q_OBJECT private: static mpListeners msmpListeners; static quint16 msuint16NextPort; quint16 muint16Port; public: clsListener(quint16 uint16Port, QObject* pParent = nullptr); ~clsListener(); //static void commonDecode(QAbstractSocket* psckIn); static clsListener* pGetListener(quint16 uint16Port); static quint16 uint16NextPort() { return ++clsListener::msuint16NextPort; } quint16 uint16Port() { return muint16Port; } signals: protected slots: void incomingConnection(qintptr sckDescriptor); }; #endif // CLSLISTENER_H
Implementations:
/** * File: clsListener.cpp * Notes: Contains implementation of the listener class * History: 2020/11/30 Created by Simon Platten * * To test, copy and paste the line below into a browser: * http://localhost:8123/?{"msgType":"ready","source":"simon"} */ #include <utility> #include "clsDebugService.h" #include "clsListener.h" #include "clsModule.h" /** * @brief clsServer::clsServer * @param sckDescriptor : Socket descriptor * @param pParent : Optional, pointer to parent */ clsServer::clsServer(qintptr sckDescriptor, QObject* pParent) : QThread(pParent) , msckDescriptor(sckDescriptor) , mpsckIncoming(nullptr) { //Register type for signals qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError"); } /** * @brief clsServer::~clsServer */ clsServer::~clsServer() { if ( isRunning() == true ) { terminate(); while( isRunning() == true ) { //Wait until thread stops } } if ( mpsckIncoming != nullptr ) { cleanup(); } } /** * @brief clsServer::cleanup */ void clsServer::cleanup() { if ( mpsckIncoming != nullptr ) { QObject::disconnect(mpsckIncoming, &QAbstractSocket::errorOccurred ,this, &clsServer::onErrorOccurred); QObject::disconnect(mpsckIncoming, &QAbstractSocket::disconnected ,this, &clsServer::onDisconnected); QObject::disconnect(mpsckIncoming, &QAbstractSocket::readyRead ,this, &clsServer::onReadyRead); mpsckIncoming->deleteLater(); mpsckIncoming = nullptr; } } /** * @brief clsServer::onDisconnected */ void clsServer::onDisconnected() { qinf() << "Disconnected"; cleanup(); } /** * @brief clsServer::onErrorOccurred * @param error : error that occurred */ void clsServer::onErrorOccurred(QAbstractSocket::SocketError error) { //Display error QString strURLencoded(QUrl::toPercentEncoding(mpsckIncoming->errorString())); qwrn() << "Socket error(" << strURLencoded << ") https://www.google.com/search?rls=en&q=socket+error+code+" << strURLencoded << "&ie=UTF-8&oe=UTF-8" << strURLencoded << ".php"; //Prevent unused parameter warning (void)error; } /** * @brief clsServer::onReadyRead */ void clsServer::onReadyRead() { if ( mpsckIncoming == nullptr ) { return; } clsModule::manageReceivedData(mpsckIncoming); } /** * @brief clsServer::run */ void clsServer::run() { QTcpSocket* pSocket(new QTcpSocket()); //Set the ID if( !pSocket->setSocketDescriptor(msckDescriptor) ) { //Something's wrong, we just emit a signal emit error(pSocket->error()); return; } //Connect socket and signal pSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1); mpsckIncoming = pSocket; QObject::connect(mpsckIncoming, &QAbstractSocket::errorOccurred ,this, &clsServer::onErrorOccurred); QObject::connect(mpsckIncoming, &QAbstractSocket::disconnected ,this, &clsServer::onDisconnected); QObject::connect(mpsckIncoming, &QAbstractSocket::readyRead ,this, &clsServer::onReadyRead); //Make this thread a loop, //thread will stay alive so that signal/slot to function properly //not dropped out in the middle when thread dies exec(); } //Static initialisation mpListeners clsListener::msmpListeners; quint16 clsListener::msuint16NextPort = 8122; //Will is increment before use /** * @brief clsListener class constructor * @param uint16Port : Port to listen on * @param pParent : Pointer to parent */ clsListener::clsListener(quint16 uint16Port, QObject* pParent) : QTcpServer(pParent), muint16Port(uint16Port) { if ( uint16Port == 0 ) { throw "Port invalid!"; } if ( clsListener::pGetListener(uint16Port) != nullptr ) { throw "Port already in use by another listener!"; } qinf() << QString("Listening to any local IP address on port: %1").arg(muint16Port); //Start listening to port if ( !listen(QHostAddress::Any, muint16Port) ) { qwrn() << "Unable to lisen to port " << muint16Port; } clsListener::msmpListeners.insert(std::make_pair(muint16Port, this)); } /** * @brief Removes listener */ clsListener::~clsListener() { if ( clsListener::msmpListeners.find(muint16Port) != clsListener::msmpListeners.end() ) { clsListener::msmpListeners.erase(muint16Port); } close(); } /** * @brief clsListener::incomingConnection * @param sckDescriptor : Socket descriptor for new connection */ void clsListener::incomingConnection(qintptr sckDescriptor) { //Every new connection will be run in a newly created thread clsServer* pThread(new clsServer(sckDescriptor, this)); //Look for module listening to this port // clsModule* pModule(pFindModuleListeningToPort(muint16Port)); //Connect signal/slot //Once a thread is not needed, it will be beleted later QObject::connect(pThread, &QThread::finished ,pThread, &QThread::deleteLater); pThread->start(); } /** * @brief clsListener::pGetListener * @param uint16Port : Port to search for listener using * @return Pointer to listener or nullptr if not found */ clsListener* clsListener::pGetListener(quint16 uint16Port) { mpListeners::iterator itrFound(clsListener::msmpListeners.find(uint16Port)); if ( itrFound != clsListener::msmpListeners.end() ) { return itrFound->second; } return nullptr; }
-
You're long enough here to know how to use a debugger and debug such warnings.. aren't you?
And searching for QT_FATAL_WARNINGS in the forum will reveal more help.QObject::connect(mpsckIncoming, &QAbstractSocket::errorOccurred ,this, &clsServer::onErrorOccurred);
And this was also discussed many times here - your slot is executed in the main thread and so QTcpSocket is accessed from the wrong thread. The forum search is something you should learn to use.
-
@Christian-Ehrlicher , Yes, thats exactly what I'm doing, just hoping someone might be able to suggest what could be wrong, apart from the logged message, everything seems to be working fine.
-
@Christian-Ehrlicher , if the error occurs in a thread, what is the correct way to manage this connection?
-
@SPlatten Do you even read my posts? I wrote what you did wrong (except that there is again no need for a thread and when using a thread reading the documentation on how to use it properly seems to be too hard)
-
@Christian-Ehrlicher , maybe because your posts are very cryptic and its not easy to see what you are trying to say.
"except that there is again no need for a thread and when using a thread reading the documentation on how to use it properly seems to be too hard"
What does that even mean ?
-
@SPlatten said in Qt Message, what does it mean, is it important ?:
What does that even mean ?
- you don't need a thread to read from a QTcpSocket but just use it because it's fancy without known what you're actually doing.
- you did not read the QThread documentation which clearly explains on how to properly use a QThread and don't care about it.
-
This post is deleted!
-
@Christian-Ehrlicher , Its actually not a problem at all, turns out the only time these messages are reported is when the application is terminated by clicking the stop button in Qt Creator.
If I close the application by clicking the close widgets on the window it doesn't exhibit the problem.
-
Do not do this.
class clsServer : public QThread { }
Instead, use a worker as Christian posted:
https://doc.qt.io/qt-6/qthread.html#details
It is critical.Another thing Christian pointed out is: why do you add QTcpSocket inside a thread?
What is the reason? -
@SPlatten
In Qt, the GUI elements (widgets) or QObject are not thread-safe, meaning they should
be created and manipulated only in the main thread. If you try to create or manipulate
GUI elements in a thread other than the main thread, you may encounter issues,
including the error message "Cannot create children for a parent that is in a different
thread."