Reputation: 2396
note: the title does not convey the question exactly, feel free to edit as is necessary
1. Info:
I have created a custom QProcess class called m_Proc
.
#include "misc_serv"
using namespace misc_serv;
class GEN_SERVSHARED_EXPORT m_Proc : public QProcess
{
Q_OBJECT
public:
int exitCode = -1;
QString _out;
s_i_combo si;
QList<s_i_combo> sch_in_List;
m_Proc(QList<s_i_combo> i_s_list, QObject *parent = 0);
m_Proc(s_i_combo i_s_obj, QObject *parent);
m_Proc(QObject *parent);
void setProcessBlocks(s_i_combo _si);
void setProcessBlocks(QList<s_i_combo> _si_list);
~m_Proc() {}
private:
s_i_combo getSearchInput();
void initConnectors();
public slots:
void myReadyReadStandardOutput();
void myFinished(int i);
signals:
void finishedSignal();
};
The purpose of this class is to use the signals emitted from the QProcess parent, which will allow me to read*()
from and write()
to the QProcess
.
When the final output is reached, the QProcess::finished(int)
, is connected to a method to assign the final output and exit code of the QProcess
a signal is then emitted from m_Proc
which will notify the parent class The signal named (quite creatively) finishedSignal
m_Proc
is handled by another parent class named gen_serv
.
#include "m_proc.h"
class GEN_SERVSHARED_EXPORT gen_serv : public QObject
{
Q_OBJECT
private:
QObject *parent;
QProcess *p;
int MSEC = 1000;
m_Proc *m;
int exitCode = -1;
QString _proc_out;
void init_connector();
private slots:
void getResults();
public:
gen_serv(QObject *_parent = new QObject());
virtual ~gen_serv();
void runCommand(const QString _prog);
void runCommand(const QString _prog, const QStringList args);
void runCommand(const QString _prog, const QString _sSearch, const QString _sInput);
void runCommand(const QString _prog, const QStringList args, const QString _sSearch, const QString _sInput);
void runCommand(const QString _prog, s_i_combo siCombo);
void runCommand(const QString _prog, const QStringList args, s_i_combo siCombo);
void runCommand(const QString _prog, QList<s_i_combo> siList);
void runCommand(const QString _prog, const QStringList args, QList<s_i_combo> siList);
QString getRunCommand_Output();
int getRunCommand_ExitCode();
QProcess* createProcess(QString cmd/*, int t_sec = 30*/);
};
gen_serv has various "constructor methods" for m_Proc
. These constructor methods calls runCommand
. These constructors with their parameters allow various processing capabilities ranging from a basic program execution to a detailed I/O process.
2. The Problem:
In my qt console application, I create a gen_serv
object, and use this to "runCommands", e.g. :
//main.cpp
gen_serv *gen_proc
gen_proc = new gen_serv();
gen_proc->runCommand("sh", QStringList()
<< "-c"
<< "echo sleeping; sleep 2; echo hello...");
qDebug() << gen_proc->_proc_out;
based on how my m_Proc works, it will should return: "hello..."
the command to be run above is the same as (to my understanding):
$ sh -c "echo sleeping; sleep 2; echo hello..."
sleeping
hello...
BUT: it returns an empty QString, and:
qDebug() << QString::number(gen_proc->exitCode);
outputs : "-1"
3. Extra code examples, etc - This led me to believe:
the issue does not lie in m_Proc
, but in my parent class gen_serv
.
Currently, after calling void gen_serv::runCommand()
, I run the QObject::connect()
as shown below (getResults()
just gets the _proc_out
and exitCode
and assigns them to gen_serv
for accessor methods):
QObject::connect(m, SIGNAL(finishedSignal()), this, SLOT(getResults()));
However this is executed, and runCommand()
returns to main.cpp
where qDebug()
immediately calls the gen_proc->_proc_out
and qDebug() will output:
_gen_proc->_proc_out = ""
_gen_proc->exitcode = -1
4. TL;DR
What I need:
I need to devise a method which will run after/or replacing the connect (in gen_serv
).
This method will wait until the signal is emitted, so the runCommand()
, which calls the QProcess.start()
, will not return until the finishedSignal
from m_Proc
is emitted, thus guaranteeing a valid output/exit code value.
Any suggestions?
Upvotes: 0
Views: 698
Reputation: 2396
I have found a solution, I cannot tell if it is a good one or not, but it works.
Possible Solution: (using QProcess::wait*()
's)
In the method (gen_serv::init_connector()
) where I call the QObject::connect()
, I changed/added a few extra lines.
void gen_serv::init_connector(){
if (m->waitForStarted()) {
QObject::connect(m, SIGNAL(finishedSignal()), this, SLOT(getResults()));
if (!m->waitForFinished())
qDebug() << "program is hanging, check m_Proc description for possible hang issues...: \n" << m->errorString();
}
else{
if (m->errorString().contains("No such file or directory"))
qDebug() << "check program and arguments - something seems wrong. Cannot find something... : \n" << m->errorString();
else
qDebug() << m->errorString();
}
}
The solution is pretty straight forward, but nonetheless, I will provide a short description:
note: I noticed that an error string like:
"execp: No such file or directory usually implies that either the
program
is not found
i.e. incorrect path or there are surplus arguments or the application does not take any arguments
connect()
the signal
and slot
. Followed by the waitForFinished()
.Reason for the waitForFinished()
is this method waits for the QProcess::finished(int) signal.
This allows the application to wait until the process has completed (which is what I require).
Hope this helps someone
Upvotes: 1