在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行

Posted

技术标签:

【中文标题】在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行【英文标题】:Make child process spawned with system() keep running after parent gets kill signals and exits 【发布时间】:2012-10-17 23:52:58 【问题描述】:

在 Linux/C++ 库中,我通过 system() 调用启动一个进程,

system("nohup processName > /dev/null&");

这似乎适用于一个自行退出的简单测试应用程序,但如果我从一个收到终止信号的 Nodejs/V8 扩展内部使用它,子进程就会被终止。我确实发现它正在运行,

system("sudo nohup processName > /dev/null&");

将 sudoers 文件设置为不需要密码,即使在父进程(节点)退出时也可以运行。有没有办法完全分离子进程,以便发送给父进程和父进程退出的信号不再对子进程产生影响?最好在 system() 调用中,而不是需要获取进程 ID 并对其执行某些操作。

【问题讨论】:

也许是值得信赖的双分叉执行器? 为此使用 sudo 似乎是一个非常糟糕的主意 是的,这并不是一个解决方案,我只是将其记录为观察。虽然我想到了使用 sudo 将用户切换到已经运行该进程的同一用户。 避免使用system(3) 启动这样的进程。你应该使用fork(2) & execve(2) 或者daemon(3)。阅读advancedlinuxprogramming.com 【参考方案1】:

与父进程分离的过程很简单:在setsid 下运行命令(因此它在新会话中启动),将标准输入、输出和错误重定向到/dev/null(或其他地方,视情况而定) ,在子shell的背景中。因为system()启动了一个新的shell,就相当于这样一个子shell,所以

system("setsid COMMAND </dev/null >/dev/null 2>/dev/null &");

完全按照需要做。在 shell 脚本中,等价于

( setsid COMMAND </dev/null >/dev/null 2>/dev/null & )

(Shell 脚本需要一个子shell,否则COMMAND 将处于当前shell 的作业控制之下。这在使用system() 时并不重要,因为无论如何它都会为该命令启动一个新的shell;shell将在命令退出时退出。)

重定向是必要的,以确保COMMAND 没有打开当前终端的描述符。 (当终端关闭时,会向所有此类进程发送一个 TERM 信号。)这意味着标准输入、标准输出和标准错误都必须重定向。上述重定向适用于 Bash 和 POSIX shell,但可能不适用于旧版本的 /bin/sh。特别是,它应该适用于所有 Linux 发行版。

setsid 开始一个新会话; COMMAND 成为其自己的进程组的进程组负责人。信号可以指向单个进程,也可以指向进程组中的所有进程。终止信号通常被发送到整个进程组(因为一个应用程序在技术上可能由多个相关进程组成)。如果父进程所属的进程组被进程组范围的信号杀死,则启动新会话可确保 COMMAND 不会被杀死。

【讨论】:

【参考方案2】:

我的猜测是整个进程组都被杀死了。你可以在子进程中尝试setpgid 来启动一个新的进程组。第一步应该是摆脱system并使用forkexecveposix_spawn

【讨论】:

以上是关于在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行的主要内容,如果未能解决你的问题,请参考以下文章

使用 c 安排警报

如何在父进程被终止的情况下保持子进程的活力

shell编程 信号处理

如何在LinuxShell中强制python退出

如何在LinuxShell中强制python退出

如何在父进程终止后终止所有子进程?