【问题标题】:Catch SIGINT in parent but kills child anyway在父母身上捕获 SIGINT 但无论如何都会杀死孩子
【发布时间】:2020-03-10 20:38:32
【问题描述】:

我有一个架构,其中一个父级产生两个子级(一个在 c++ 中,另一个在 python 中)。父级产生以下类:

export class subProcess {
    protected cmd: string;
    protected args: string[];
    protected process: child.ChildProcess;

    constructor(cmd: string, args: string[]) {
        this.cmd     = cmd;
        this.args    = args;
        this.process = null;
    }

    spawn(): void {
        this.process = child.spawn(this.cmd, this.args);

        const rlout = readline.createInterface({
            input: this.process.stdout,
        });
        rlout.on('line', line => this.logger.info(line));

        const rlerr = readline.createInterface({
            input: this.process.stderr,
        });
        rlerr.on('line', line => this.logger.error(line));

        this.process.on('exit', (code: number) => {
            this.logger.info(`exit code: ${code}`);
        });
    }

当我用 Ctrl-C 中断父进程时,信号 SIGINT 在父进程中被捕获,以便能够首先断开连接并优雅地杀死子进程:

process.on('SIGINT', () => {
    this.bus.disconnect();
});

disconnect 是一个通过 ZeroMQ 向孩子发送"exit_process" 命令的函数。此命令在正常行为中运行良好。但问题是,当我按下 Ctrl-C 时,SIGINT 被父级捕获并执行disconnect 函数(如预期的那样),但它似乎也将SIGINT 传播给孩子。实际上,通过 ZeroMQ 发送的 "exit_process" 命令达到了超时(这意味着子进程从未收到/应答),而子进程通过 exit 事件发出返回的代码。

关键是,出于项目原因,我无法分离和/或取消引用子项,或管理子项中的信号。我希望父母能够捕捉到SIGINT,而不会将其传播给孩子。

还有一点,我尝试在subProcess 类中添加以下内容,但没有成功:

this.process.on('SIGINT', () => {
    console.log('SIGINT received. Do nothing');
});

【问题讨论】:

  • SIGINT 被发送到整个进程组。见this nodejs issueWikipedia
  • 所以subProcess 类中的this.process.on('SIGINT', () => { console.log(...)}); 应该是caugth,不是吗?但显然,似乎并非如此。无论如何,它是通过孩子的标准输入还是其他方式发送?

标签: node.js child-process sigint


【解决方案1】:

您的SIGINT 正在传递给整个进程组——请参阅this section on Wikipedia。但是,由于子进程管道的建立方式,您可能看不到任何输出。

当产生一个新的子进程时,你可以提供stdio options:

this.process = child.spawn(this.cmd, this.args, {stdio: 'inherit'});

以上导致父进程的process.stdinprocess.stdoutprocess.stderr被子进程继承。如果您使用这种方法,您会看到您的孩子收到了SIGINT

默认行为是创建separate streams,这就是您看不到console.log 的原因。您还可以收听孩子的标准输出流:

this.process.stdout.on('data', data => console.log(data.toString()));

【讨论】:

    猜你喜欢
    • 2012-01-03
    • 2016-11-09
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    相关资源
    最近更新 更多