I have a program that starts a workflow, waits for it to finish (listens for a signal SIGCHLD), and then starts another workflow. Inside my workflows, I run QProcessthat calls another program. In my test case, I call the touchstandard Linux command.
I use fork()and execv()to run workflows.
The problem is that it QProcessonly succeeds in the first workflow. After the advent of new workflows, he QProcessnever says that it was completed. The team touchitself does its job perfectly. But in all workflows except the first, he becomes a zombie at the end.
Here's the minimum test program:
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
#include <signal.h>
#include <wait.h>
void spawnWorkerProcess();
void launchQProcess();
void catchSigChild(int i);
void execChild();
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
if (argc > 1)
{
launchQProcess();
}
else
{
if (signal(SIGCHLD, catchSigChild) == SIG_ERR)
{
qFatal("could not attach to SIGCHLD");
}
spawnWorkerProcess();
return app.exec();
}
}
void spawnWorkerProcess()
{
pid_t pid = fork();
if (pid == -1)
{
qCritical() << "FORK ERROR";
exit(1);
}
else if (pid == 0)
{
execChild();
exit(1);
}
else
{
qWarning() << "FORK OK";
}
}
void
execChild()
{
unsigned i = 0;
const char **argv = new const char *[3];
QByteArray ba = qApp->applicationFilePath().toLocal8Bit();
argv[i++] = ba.data();
argv[i++] = "worker";
argv[i++] = 0;
qWarning() << "execv ..." << argv;
execv(argv[0], const_cast<char *const *>(argv));
qWarning() << "execv OK";
delete[] argv;
}
void catchSigChild(int i)
{
qCritical() << Q_FUNC_INFO << i;
pid_t cpid;
int stat;
while ((cpid = waitpid(0, &stat, WNOHANG)) > 0)
{
static int counter = 0;
counter++;
if (counter < 5)
{
qDebug() << "SPAWN:" << counter;
spawnWorkerProcess();
}
else
{
qCritical() << "RESPAWN LIMIT REACHED! Bye-bye!";
exit(0);
}
}
}
void
launchQProcess()
{
QProcess pr;
qWarning() << "start QProcess " << qApp->applicationPid();
pr.start(QString("touch /tmp/test/%1").arg(qApp->applicationPid()), 0);
if (! pr.waitForFinished(3000))
{
qWarning() << "QProcess FAIL" << qApp->applicationPid() << pr.state() << "\n";
delete (int*) 1;
}
else
{
qWarning() << "QProcess OK" << qApp->applicationPid() << pr.state() << "\n";
}
}
source
share