c – fork()和execv()之后的QProcess问题
发布时间:2020-12-16 07:09:08 所属栏目:百科 来源:网络整理
导读:我有一个程序,它启动一个工作进程,等待它完成(监听SIGCHLD信号),然后启动另一个工作进程.在我的工作进程中,我启动了一个调用另一个程序的QProcess.在我的测试用例中,我称之为touch – 标准的 Linux命令. 我使用fork()和execv()来启动工作进程. 问题是QProces
我有一个程序,它启动一个工作进程,等待它完成(监听SIGCHLD信号),然后启动另一个工作进程.在我的工作进程中,我启动了一个调用另一个程序的QProcess.在我的测试用例中,我称之为touch – 标准的
Linux命令.
我使用fork()和execv()来启动工作进程. 问题是QProcess仅在第一个工作进程中成功完成.生成新的工作进程后,QProcess永远不会说它已完成.触摸命令本身一直都很好.但是在除了第一个工作流程之外的所有工作流程中,它最终变成了僵尸. 这是一个最小的测试程序: #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) // worker process { launchQProcess(); } else // main process { 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) { /* the child process */ 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; // we don't want to wait for QProcess timeout,so doing crash } else { qWarning() << "QProcess OK" << qApp->applicationPid() << pr.state() << "n"; } } 解决方法
你永远不应该在信号处理程序中调用glibc.处理程序是异步调用的,这意味着它们可以中断系统调用.这些电话可能不是可重入的.要了解有关此内容的更多信息,请查看以下页面:
http://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |