当前位置: 首页 > 知识库问答 >
问题:

节点pty.js产生一个进程,它本身产生子进程,当节点被杀死时,子进程不会死亡

龙哲
2023-03-14

使用Ubuntu 13.10和运行节点v0.10.0。我正在使用pty.jsv0.2.4生成一个程序(需要在交互式环境中运行)。该程序是用C编写的,并分叉子进程本身。

我已经编写了一个非常精简的C程序版本(我称之为“forktest”),它具有产生此问题所需的最小值,并包含以下内容:

#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(void)
{
    pid_t childPID;
    childPID = fork();
    if(childPID >= 0) {
        if(childPID == 0) {
            signal(SIGHUP, SIG_IGN);
            while(1) {
              printf("Child Process\n");
              fflush(stdout);
              usleep(500000);
            }
        } else {
            printf("Parent process\n");
            fflush(stdout);
            getchar();
        }
    } else {
        printf("Fork failed, exiting\n");
        return 1;
    }
    return 0;
}

我还整理了一个最小节点脚本,用coffeescript(test.coffee)编写,它运行程序,如下所示:

pty = require 'pty.js'

command = './forktest'
example = pty.spawn command, null
example.on 'data', (data) ->
  console.log data
example.on 'exit', ->
  console.log 'example exited'

运行节点脚本“coffee test.coffee”时,可以看到输出(“父进程”和“子进程”)。此外,进程的层次结构在 ps 中正确显示(“ps faux”):

lightdm
 \_ /usr/bin/X -core :0 -auth /var/run/lightdm/root/:0 -no
 \_ lightdm --session-child 12 21
     \_ init --user
         \_ gnome-terminal
             \_ bash
                 \_ node /usr/local/bin/coffee test.coffee
                     \_ ./forktest
                         \_ ./forktest

但是,当退出 coffeescript(使用 ctrl-c)时,父分叉测试进程也会按预期退出,但子分叉进程被抛在后面,然后 'ps faux' 的输出如下所示:

lightdm
 \_ /usr/bin/X -core :
 \_ lightdm --session-
     \_ init --user
         \_ ./forktest

我调查过这是因为在子进程中忽略了挂起信号:

signal(SIGHUP, SIG_IGN);

如果我在节点中使用child_process模块中的spawn:

{spawn} = require 'child_process'

command = './forktest'
example = spawn command

example.stdout.on 'data', (data) ->
  console.log String data
example.on 'exit', ->
  console.log 'example exited'

以同样的方式退出coffeescript应用程序(ctrl-c),当它退出时,forktest的父进程和子进程都会消失,因此它看起来与pty.js的工作方式有关。

我无法编辑(消除对信号的忽略)并将原始C程序分发给用户,所以我正在寻找解决这个问题的方法

一种解决方法是通过以下方式捕获节点的中断信号:

process.on 'SIGINT', (data) ->
  # kill the parent / child process manually

无论如何,我可能应该这样做。但是如果咖啡脚本过程被杀死,而不是中断,它仍然会遭受同样的问题,并将孩子抛在后面。据我所知,没有办法在节点中捕获SIGKILL?

用pty.js生成的程序的子进程在节点被杀死时没有被销毁是有原因的吗?

共有1个答案

邵兴庆
2023-03-14

您在 POSIX 系统如何处理杀戮进程方面遇到了一个微妙的问题。

当进程被终止时,内核会重新定义父进程是谁。与子进程退出并通知其父进程不同,如果父进程在退出时没有向子进程发送信号,则子进程不会收到任何通知。内核只是将其父id重新定义为init进程。

因此,默认情况下,当其父级退出时,没有子级退出。那么,当父母辞职时,孩子们怎么会被杀呢?每个进程都有一个进程组id。这默认为启动时其父进程的进程组id。如果进程组因进程死亡而成为孤儿,那么内核可能会向进程组的所有成员发送<code>SIGHUP</code>和<code>SIGCONT</code>消息。这给了子进程一个退出的机会,但他们不必退出。如果他们不退出,那么他们就是孤立进程,并且他们将父进程id设置为init进程。

巧合的是,这就是分叉创建守护进程的工作方式。

因此,要解决您的问题,请确保子进程是同一进程组id的一部分。这应该让它们接收到终止子进程的信号。然而,如果他们忽略了这个信号,你实际上只有一个选择。

生成一个包装程序,它只生成您的实际进程,并在“真实”父级和“真实”子级之间来回传递所有内容。然后,如果SIGHUP被发送到您的包装器,请向子级发送SIGKILL以强制退出。

 类似资料:
  • 问题内容: 我正在使用child_process.spawn()从在Ubuntu上运行的Node.JS应用程序启动脚本。据我所知,标准的分叉或生成的* nix进程通常不会在父进程死后死亡,但是当从Node.JS生成进程时,它们似乎在我的应用程序崩溃或被ctrl-c等终止时被杀死。 。 为什么会这样,并且有解决办法?我似乎在child_process API中找不到任何明显的选项。 我的应用程序启动

  • 问题内容: 我正在python中使用subprocess模块​​运行一些shell脚本。如果shell脚本运行时间很长,我想杀死该子进程。我认为如果将其传递给我的陈述就足够了。 这是代码: 我已经用一些运行120秒的shell脚本测试了此调用。我期望子进程在30秒后被杀死,但是实际上该进程正在完成120秒脚本,然后引发了Timeout Exception。现在的问题是如何通过超时杀死子进程? 问题

  • 问题内容: 我有一个程序生成并与CPU繁重,不稳定的进程通信,而不是由我创建的。如果我的应用程序崩溃或被杀死,我也希望子进程也被杀死,因此用户不必跟踪它们并手动杀死它们。 我知道以前已经讨论过该主题,但是我已经尝试了所有描述的方法,但似乎没有一种方法能够经受住测试的考验。 我知道这是有可能的,因为终端一直在这样做。如果我在终端中运行某些程序并杀死该终端,则这些东西总是会死掉。 我试过了,双叉和。不

  • 我如何在linux(ubuntu)中杀死这个进程?

  • 问题内容: 我正在用C / C ++ 创建子进程。 当父进程结束(或由于某种原因被杀死)时,我也希望所有子进程也被杀死。 这是系统自动完成的吗?还是我必须自己做? 谢谢。 问题答案: 否。如果父进程被杀死,则子进程将成为init进程的子进程(该进程的进程ID为1,并由内核作为第一个用户进程启动)。 初始化过程会定期检查新的子代,然后等待它们(从而释放由其返回值分配的资源)。

  • 问题内容: 我从python脚本生成了5个不同的进程,如下所示: 我的问题是,当父进程(主脚本)以某种方式被杀死时,子进程继续运行。 当父进程被杀死时,有没有办法杀死这样生成的子进程? 编辑:我正在尝试: 但这似乎不起作用 问题答案: 我自己也遇到了同样的问题,我有以下解决方案: 打电话之前,您可以设置。然后如此处所述python.org multiprocessing 进程退出时,它将尝试终止其