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

Phe*_*ide 2 c c++ linux process node.js

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

system("nohup processName > /dev/null&");
Run Code Online (Sandbox Code Playgroud)

对于一个自行退出的简单测试应用程序来说,这似乎工作得很好,但如果我从获得终止信号的 Nodejs/V8 扩展内部使用它,子进程就会被终止。我确实发现跑步,

system("sudo nohup processName > /dev/null&");
Run Code Online (Sandbox Code Playgroud)

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

Nom*_*mal 5

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

system("setsid COMMAND </dev/null >/dev/null 2>/dev/null &");
Run Code Online (Sandbox Code Playgroud)

正是需要的。在 shell 脚本中,等价的是

( setsid COMMAND </dev/null >/dev/null 2>/dev/null & )
Run Code Online (Sandbox Code Playgroud)

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

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

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