Qt console application leaves terminal open on termination
-
@jsulm , its a bit like a web-server, multiple clients, each client (module) does not monopolise the application by holding up communications, so to keep it as responsive as possible each client gets it's own thread.
@SPlatten , I've re-written the launch function:
QProcess* clsScriptHelper::pLaunch(QString strApp, QStringList& slstArgs) { QString strFullPath(clsDebugService::strGetUserFolder(strApp)); qdbg() << "Checking for PID for: " << strFullPath; QProcess* pModule = nullptr; qint64 int64PID; if ( blnGetPID(strFullPath, int64PID) == true ) { //Process already running, no action required } else { int intLastSep = strFullPath.lastIndexOf(QDir::separator()); qdbg() << "Process is NOT running, launching"; if ( intLastSep > 0 ) { QString strName = strFullPath.mid(intLastSep + 1) ,strPath = strFullPath.mid(0, intLastSep + 1); pModule = new QProcess(this); pModule->setArguments(slstArgs); pModule->setWorkingDirectory(strPath); pModule->setProgram(strName); pModule->start(); int64PID = pModule->processId(); if ( int64PID == 0 ) { delete pModule; pModule = nullptr; } } } if ( int64PID > 0 ) { qdbg() << "Process: " << strFullPath << " started, PID: " << QString::number(int64PID); } return pModule; }
This works a lot better and now the child process is terminated and the terminal window closes when the main application terminates, however I am still seeing in the Application Output:
W00000000000000000014:QObject: Cannot create children for a parent that is in a different thread. W00000000000000000015:(Parent is clsScriptHelper(0x10320da10), parent's thread is QThread(0x10320aad0), current thread is clsThread(0x10325d1a0)
Is there any way to avoid/prevent this?
-
@SPlatten , I've re-written the launch function:
QProcess* clsScriptHelper::pLaunch(QString strApp, QStringList& slstArgs) { QString strFullPath(clsDebugService::strGetUserFolder(strApp)); qdbg() << "Checking for PID for: " << strFullPath; QProcess* pModule = nullptr; qint64 int64PID; if ( blnGetPID(strFullPath, int64PID) == true ) { //Process already running, no action required } else { int intLastSep = strFullPath.lastIndexOf(QDir::separator()); qdbg() << "Process is NOT running, launching"; if ( intLastSep > 0 ) { QString strName = strFullPath.mid(intLastSep + 1) ,strPath = strFullPath.mid(0, intLastSep + 1); pModule = new QProcess(this); pModule->setArguments(slstArgs); pModule->setWorkingDirectory(strPath); pModule->setProgram(strName); pModule->start(); int64PID = pModule->processId(); if ( int64PID == 0 ) { delete pModule; pModule = nullptr; } } } if ( int64PID > 0 ) { qdbg() << "Process: " << strFullPath << " started, PID: " << QString::number(int64PID); } return pModule; }
This works a lot better and now the child process is terminated and the terminal window closes when the main application terminates, however I am still seeing in the Application Output:
W00000000000000000014:QObject: Cannot create children for a parent that is in a different thread. W00000000000000000015:(Parent is clsScriptHelper(0x10320da10), parent's thread is QThread(0x10320aad0), current thread is clsThread(0x10325d1a0)
Is there any way to avoid/prevent this?
@SPlatten said in Qt console application leaves terminal open on termination:
Is there any way to avoid/prevent this?
Yes, doing multithreading in a proper way. As I wrote before: you are doing something wrongly somewhere in your code. And the warning even tells you what: you are using an objects as parent for another object which lives in another thread.
You should read this: https://doc.qt.io/qt-5/qobject.html#thread-affinity -
@SPlatten said in Qt console application leaves terminal open on termination:
Is there any way to avoid/prevent this?
Yes, doing multithreading in a proper way. As I wrote before: you are doing something wrongly somewhere in your code. And the warning even tells you what: you are using an objects as parent for another object which lives in another thread.
You should read this: https://doc.qt.io/qt-5/qobject.html#thread-affinity@jsulm, the difficulty is that the method of calling the launch function is from an exported / exposed (not sure of correct terminology) API call from the C++ to JavaScript:
Q_INVOKABLE QJsonObject use(QJsonValue strModule);
In the JavaScript:
xmleng.use("mdFileIO");
Where xmleng is exposed to the JavaScript by the engine:
const QString strXMLEngine("xmleng"); if ( objGlobal.hasProperty(strXMLEngine) == false ) { clsScriptHelper* pScriptHlpr = clsScriptHelper::pobjGetInstance(); if ( pScriptHlpr != nullptr ) { QJSValue result = pobjScriptEng->newQObject(pScriptHlpr); objGlobal.setProperty(strXMLEngine, result); } }
The use function in C++:
/** * @brief clsScriptHelper::use * @param strModule : Name of the module to use * @return JSON object containing pass on when using the module */ QJsonObject clsScriptHelper::use(QJsonValue strModule) { clsXMLnode* pobjRoot = clsXMLnode::spobjGetRoot(); Q_ASSERT_X(pobjRoot!=nullptr, "clsScriptHelper::use" , "pobjRoot is NULL!"); QString strModulesPath = pobjRoot->strGetAttribute(clsXMLnode::mscszAttrModules) ,strModuleName = strModule.toString(); //Is module already loaded? mpModules::iterator itrModule; QJsonObject objModule; QStringList slstSlot; if ( clsScriptHelper::blnGetModule(strModuleName, &itrModule) == true ) { //Module already loaded, get the process id objModule = itrModule->second; } else { //Module not loaded yet, attempt to start the module QString strFullPath(strModulesPath + strModule.toString()); QStringList slstArgs; slstArgs << QString::number(clsSocketServer::mscuint16port); slstArgs << QString::number(clsSocketServer::uint16NextModulePort()); slstArgs << QString::number(QCoreApplication::applicationPid()); QProcess* pProcess; if ( (pProcess = pLaunch(strFullPath, slstArgs)) != nullptr ) { //Module has been successfully started, save its PID qint64 int64PID = pProcess->processId(); objModule.insert(clsJSON::mscszModule, strModule); objModule.insert(clsScriptHelper::mscszPID, QJsonValue(int64PID)); msmpModules.insert(std::make_pair(strModuleName, objModule)); //Register JSON decoders QString strKey(strModule.toString() + clsJSON::msccColon + QString(clsJSON::mscszCmdHB)); clsJSON::registerDecoder(strKey, blnDecodeHeartbeat); } } return objModule; }
-
@SPlatten said in Qt console application leaves terminal open on termination:
Is there any way to avoid/prevent this?
Yes, doing multithreading in a proper way. As I wrote before: you are doing something wrongly somewhere in your code. And the warning even tells you what: you are using an objects as parent for another object which lives in another thread.
You should read this: https://doc.qt.io/qt-5/qobject.html#thread-affinity