如何生成不会随父级一起死亡的子进程?
How to Spawn Child Processes that Don't Die with Parent?
我有一个C++程序,它可以作为其他程序的监督程序。如果它检测到进程不再运行,它将通过system
重新启动进程。问题是,如果我杀死看门狗进程,它启动的任何进程也会死亡。
void* ProcessWatchdog::worker(void* arg)
{
//Check if process is running
if( !processRunning )
system("processName /path/to/processConfig.xml &");
}
新的子进程将正确启动,并且运行时不会出现任何问题。但是当父进程(现在这个ProcessWatchdog
进程)死亡时,子进程也会死亡。如何生成完全独立于父进程的子进程?
我尝试过使用pclose
和popen
,运行启动进程的shell脚本,以及其他一些策略,但都无济于事。我忽略了子进程中的SIGHUP
信号,但它们仍然会消亡。
因此,理想情况下,我想告诉系统启动一个完全独立于父级的过程。我希望孩子的trace
以孩子结束,让它/系统一开始就不知道ProcessWatchdog
启动了它。
有什么办法我能做到这一点吗?
我在Linux上用C++写这篇文章。
这个有点老,但没有得到完整的答案。以下是我在嵌入式系统上所做的,以生成一个与父级没有关系的bash子级。请注意,我执行了一个bash shell,然后在另一个bash-shell中运行我的命令。在您的情况下,这可能没有必要。对我来说,它允许我做一些没有它就不能正常工作的I/O重定向。
两个重要的概念是setsid()和doublefork()。这两者的结合可以防止在孤儿完成时创建僵尸,也可以防止在父对象完成时杀死孤儿。
可能会出现许多其他问题,如继承的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 FAILEDn"); return pid; }
if (pid == 0) { // CHILD
setsid(); // Make this process the session leader of a new session
pid = fork();
if (pid < 0) { printf("FORK FAILEDn"); 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 orphann");
return -1;
}
}
不要使用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
}
您应该避免使用系统。
不要从具有设置用户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
...
尝试在进程名称之前使用system
和setsid
。
system("setsid processname /path/to/processConfig.xml &");
这将在新会话中启动程序。
您可能对守护进程(3)库函数(内部使用两个嵌套的fork(2)系统调用)感兴趣。之后,使用相关的execve(2)syscall(或相关的exec(3)函数)。。。
您应该阅读高级Linux编程了解更多信息。
中有一个execvp示例https://github.com/w-A-L-L-e/wash/blob/master/src/wash.cpp.传递命令行参数有时是unistd的exec*函数的问题,而传递环境可能需要一些工作。不管怎样,希望它能帮助。。。
- 终止 QProcess 不会终止子进程
- 什么时候最好在子进程中使用 CPU 或 I/O 密集型代码 [ C++ ]
- 子进程更新共享 mmap 内存,但父进程没有更改
- 使用 waitpid 时等待子进程终止
- 使用重定向标准处理子进程中的 kbhit
- 由 JOB 中的进程启动的子进程是否可以将 JOB 属性设置为脱离作业?
- 是否可以将子进程的 stdout 重定向到父进程中的另一个文件?
- kill() 总是返回 0(成功),即使在子进程已经结束之后?
- 为什么使用与父级声明的 std::function 在与子级一起使用时会显示错误?
- 父进程和子进程之间的 POSIX 信号量
- 检测到由于操作系统内存不足而导致子进程终止
- 使用system()创建独立的子进程
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 在 Bash 脚本中处理来自子进程的信号
- Qt C++ - 如何成功将数据传递给子进程?
- C++ 窗口本地系统模拟在子进程中失败
- 将类型化数组写入子进程 stdin 无法正常工作
- 将 nodejs 脚本作为子进程执行(而不是从其他脚本执行)
- 将gcov与子进程和共享库一起使用时没有覆盖范围
- 如何生成不会随父级一起死亡的子进程?