2013-07-11 79 views
5

我有一个C++程序,充当其他人的看门狗。如果它检测到一个进程不再运行,它将通过system重新启动它。问题是,如果我杀了看门狗进程,它启动的任何进程也会死掉。如何生成不会与父母一起死亡的子进程?

void* ProcessWatchdog::worker(void* arg) 
{ 
    //Check if process is running 
    if(!processRunning) 
     system("processName /path/to/processConfig.xml &"); 
} 

新的子进程正常启动,运行没有任何问题。但是当父母(现在这个ProcessWatchdog过程)死亡时,孩子也死了。我如何产生一个完全独立于父代的子进程?

我试过使用pclosepopen,运行启动进程的shell脚本和其他一些策略,但都无济于事。我忽略了子进程中的SIGHUP信号,但它们仍然死亡。

所以理想情况下,我想告诉系统启动一个完全独立于父系的进程。我希望孩子的trace以孩子结束,并且系统不知道ProcessWatchdog首先启动它。

有没有一种方法可以做到这一点?

我正在用C++写在Linux上。

+0

[使子系统产生的子进程()继续运行后,父母获取杀死信号和退出]可能的重复(http://stackoverflow.com/questions/12945189/make-child-进程产生与系统保持运行后父母得到杀死sig) –

+0

我不认为使用系统是一个好主意.... – Alexis

+0

为什么不使用系统一个好主意?除了明显的安全问题?我在一个非常受控制的环境中在嵌入式系统上执行此操作,并且我不担心错误的系统调用。我应该警惕另一个原因吗? –

回答

0

尝试使用systemsetsid进程名之前。

system("setsid processname /path/to/processConfig.xml &"); 

这将在新的会话中启动程序。

3

不要使用system(...)它不是多线程安全的。

int pid = fork(); 

if(pid==0) 
{ 
    int rc = execv("processname", "/path/to/processConfig.xml &"); 
    if(rc == -1) 
    { 
    printf(stderr, "processname failed to start. %d", errno); 
    } 
    ... 
} 
else 
{ 
    //continue with the parent 
} 
+3

您可否详细说明'不是多线程安全'? –

+0

execv在第二个参数中需要char ** – Alexis

1

您应该避免使用系统。

不要从一个程序设置用户ID或设置组ID 特权使用system(),因为一些环境变量 奇怪的值可能被用来破坏系统的完整性。改为使用exec(3)系列 函数。

,如果你想检查返回值或其他任何

只是去execl

#include <unistd.h> 
#include <stdlib.h> 
pid_t pid = fork() 
if (pid == -1) 
{ 
    exit(EXIT_FAILURE); 
} 
else if (pid == 0) 
{ 
    if (execl("processname", "processname", "/path/to/processConfig.xml", NULL) == -1) 
    exit(EXIT_FAILURE); 
} 
else 
... 
4

这是一个有点老,但没有得到完整的答案。下面是我在嵌入式系统上完成的一项工作,它生成一个与父项无关的bash子项。请注意,我运行一个bash shell,然后在另一个bash shell中运行我的命令。在你的情况下这可能不是必要的。对我来说,它允许我做一些I/O重定向,如果没有它,它将无法正常工作。

两个重要的概念是setsid()和双叉()。这两者的组合可以防止孤儿在完成时创建僵尸,并且可以防止父母完成后孤儿被杀。

还有很多其他问题可能出现,如继承的I/O句柄,工作目录等,但此代码完成基本工作。

int spawn_orphan(char* cmd) { 
    char command[1024]; // We could segfault if cmd is longer than 1000 bytes or so 
    int pid; 
    int Stat; 
    pid = fork(); 
    if (pid < 0) { perror("FORK FAILED\n"); return pid; } 
    if (pid == 0) { // CHILD 
     setsid(); // Make this process the session leader of a new session 
     pid = fork(); 
     if (pid < 0) { printf("FORK FAILED\n"); exit(1); } 
     if (pid == 0) { // GRANDCHILD 
      sprintf(command,"bash -c '%s'",cmd); 
      execl("/bin/bash", "bash", "-c", command, NULL); // Only returns on error 
      perror("execl failed"); 
      exit(1); 
     } 
     exit(0); // SUCCESS (This child is reaped below with waitpid()) 
    } 

    // Reap the child, leaving the grandchild to be inherited by init 
    waitpid(pid, &Stat, 0); 
    if (WIFEXITED(Stat) && (WEXITSTATUS(Stat) == 0)) { 
     return 0; // Child forked and exited successfully 
    } 
    else { 
     perror("failed to spawn orphan\n"); 
     return -1; 
    } 
} 
相关问题