Nodejs中childprocess为什么捕获不到SIGINT信号

Nodejs中childprocess为什么捕获不到SIGINT信号

father.js var spawn = require(‘child_process’).spawn; var child = spawn(‘node’,[‘child.js’]);

setInterval(function(){ child.kill(‘SIGINT’); },2000);

child.on(‘exit’,function(code,signal){ console.log('process exit ‘+code+’ '+signal); });

child.js process.stdin.resume(); process.on(‘SIGINT’, function() { console.log(‘Got SIGINT. Press Control-D to exit.’); });

为什么子进程捕获不到父进程的信号? 如果单独运行node child.js,通过ctrl+c,却可以捕捉到


4 回复

Node.js 中 childprocess 为什么捕获不到 SIGINT 信号

在 Node.js 中使用 child_process 模块时,你可能会遇到一个问题:子进程无法捕获来自父进程的 SIGINT 信号。本文将探讨这个问题的原因,并提供一个示例来说明如何正确处理这种情况。

示例代码

首先,我们来看一下你的示例代码:

father.js

var spawn = require('child_process').spawn;
var child = spawn('node', ['child.js']);

setInterval(function(){
    child.kill('SIGINT');
}, 2000);

child.on('exit', function(code, signal) {
    console.log('Process exit ' + code + ' ' + signal);
});

child.js

process.stdin.resume();
process.on('SIGINT', function() {
    console.log('Got SIGINT. Press Control-D to exit.');
});

问题分析

当你从父进程中发送 SIGINT 信号给子进程时,子进程可能无法捕获到该信号。这是因为 SIGINT 信号默认被传递给了主进程(即父进程),而不是子进程。

解决方案

要解决这个问题,我们需要确保子进程正确地捕获 SIGINT 信号。你可以通过修改子进程的代码来实现这一点。

改进后的 child.js

process.stdin.resume();

// 设置一个定时器来模拟长时间运行的任务
setTimeout(() => {}, 1000000);

process.on('SIGINT', function() {
    console.log('Got SIGINT. Press Control-D to exit.');
    process.exit(); // 退出子进程
});

改进后的 father.js

var spawn = require('child_process').spawn;
var child = spawn('node', ['child.js']);

setInterval(function(){
    child.kill('SIGINT');
}, 2000);

child.on('exit', function(code, signal) {
    console.log('Process exit ' + code + ' ' + signal);
});

解释

  1. 子进程代码修改

    • 在子进程中添加了一个长时间运行的任务(setTimeout),以模拟实际的应用场景。
    • 子进程捕获 SIGINT 信号并输出一条消息,然后调用 process.exit() 退出子进程。
  2. 父进程代码

    • 父进程每隔两秒向子进程发送一次 SIGINT 信号。
    • 父进程监听子进程的 exit 事件,以便在子进程退出时打印相关信息。

通过这种方式,子进程能够正确地捕获 SIGINT 信号,并在接收到信号后正常退出。


node.js版本 0.10.17

首先fatcher.js中少了一句话

child.stdout.pipe(process.stdout);

其次运行在windows下不行,但在linux下正常工作,看来平台还是要选对啊。

在Node.js中,child_process模块中的子进程默认不会继承父进程的标准输入流(stdin),因此当使用SIGINT(通常是Ctrl+C)时,子进程可能无法捕获到这个信号。

在你的例子中,父进程试图向子进程发送SIGINT信号,但子进程没有捕获到这个信号。这是因为SIGINT信号默认不会被传递给子进程。子进程需要显式地启用对这些信号的处理。

示例代码修正

father.js

const { spawn } = require('child_process');

const child = spawn('node', ['child.js'], {
    stdio: 'inherit' // 将标准输入流传递给子进程
});

setInterval(() => {
    child.kill('SIGINT');
}, 2000);

child.on('exit', (code, signal) => {
    console.log(`Process exited with code ${code} and signal ${signal}`);
});

child.js

process.stdin.resume(); // 确保子进程监听标准输入
process.on('SIGINT', () => {
    console.log('Got SIGINT. Press Control-D to exit.');
});

解释

  1. stdio: ‘inherit’:在创建子进程时,将stdio选项设置为'inherit',这样子进程会继承父进程的标准输入流。这使得子进程能够接收到SIGINT信号。

  2. process.stdin.resume():确保子进程监听标准输入流,以便正确处理SIGINT信号。

  3. child.kill(‘SIGINT’):父进程发送SIGINT信号给子进程。由于设置了stdio: 'inherit',子进程能够捕获到这个信号。

通过这种方式,子进程就能够正确地捕获到父进程发送的SIGINT信号了。

回到顶部