c++ - Problems with QProcess after fork() and execv() -
i have program launches worker process, waits finish (listens sigchld
signal) , launches worker process. inside worker processes launch qprocess
calls program. in test case call touch
- standard linux command.
i use fork()
, execv()
launch worker processes.
the problem qprocess
finishes in first worker process only. after new worker processes spawned, qprocess
never says finished. touch
command job fine time. in worker processes except first 1 becomes zombie in end.
here's minimal 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) // worker process { launchqprocess(); } else // main process { if (signal(sigchld, catchsigchild) == sig_err) { qfatal("could not attach sigchld"); } spawnworkerprocess(); return app.exec(); } } void spawnworkerprocess() { pid_t pid = fork(); if (pid == -1) { qcritical() << "fork error"; exit(1); } else if (pid == 0) { /* child process */ execchild(); exit(1); } else { qwarning() << "fork ok"; } } void execchild() { unsigned = 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; // don't want wait qprocess timeout, doing crash } else { qwarning() << "qprocess ok" << qapp->applicationpid() << pr.state() << "\n"; } }
you should never make calls glibc within signal handler. handlers called asynchronously, means can interrupt system calls. calls may not reentrant. learn more this, check following page:
http://www.gnu.org/software/libc/manual/html_node/nonreentrancy.html
Comments
Post a Comment