Nodejs - 进程在退出时挂起(Ctrl + C)

Mad*_*d0g 18 child-process node.js

我有一个node.js项目做了很多事情,它产生子进程,它打开一个http和socket.io服务器等.

当我从控制台运行它时,关闭它Ctrl+C,它只是挂起.从webstorm开始,停止这个过程分为两个步骤,首先我点击停止,然后我需要再次点击按钮,只有第二次按钮是一个头骨图标.

现在,我明白它留下了一些开放或悬挂的东西,但我无法弄清楚是什么,我试图跟踪我开始一个过程的所有地方,并确保我正确地杀死它们.

有没有办法调试这个并找出是什么让我的进程挂起?可能是打开写入流并永远不会关闭的日志记录吗?我甚至不确定什么样的东西会使SIGINT上的进程挂起.

编辑:我已下载,pstree以查看主进程生成的任何子进程是否保持活动状态.看起来它们都正常终止 - 主节点进程是唯一剩下的.

Tim*_*lla 36

脚本本身负责在听到SIGINT事件后正确关闭,因为默认处理程序(终止进程)被禁用.

看看这个示例程序:

process.on('SIGINT', function() {
    console.log('SIGINT');
});
console.log('PID: ', process.pid);

var http = require('http'); // HTTP server to keep the script up long enough
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Run Code Online (Sandbox Code Playgroud)

执行它然后尝试杀死它:它将无法工作.该SIGINT信号总是会得到传递给您的自定义生成的信号处理.为了正确关闭该过程,您必须手动调用process.exit():

process.on('SIGINT', function() {
    console.log('SIGINT');
    process.exit();
});
console.log('PID: ', process.pid);

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Run Code Online (Sandbox Code Playgroud)

process.exit() 将:

  1. 设置一些内部标志
  2. 打电话process.on('exit')处理程序
  3. 呼叫 process.reallyExit
  4. 将调用 C++ exit()函数,因此process.exit()最终的并将导致关闭(除非您通过on('exit')处理程序中的无限循环阻止执行).

长话短说:你的代码可能会听SIGINT某个地方.您可以通过以下方式获取这些侦听器的列表:

var listeners = process.listeners('SIGINT');
Run Code Online (Sandbox Code Playgroud)

你甚至可以在控制台上打印它们:

for (var i = 0; i < listeners.length; i++) {
    console.log(listeners[i].toString());
}
Run Code Online (Sandbox Code Playgroud)

使用我上面提供的信息,您可以轻松编译另一个SIGINT处理程序,它将列出所有处理程序,然后干净地退出进程,希望引导您走向顽皮的路径:

process.on('SIGINT', function() {
    console.log('Nice SIGINT-handler');
    var listeners = process.listeners('SIGINT');
    for (var i = 0; i < listeners.length; i++) {
        console.log(listeners[i].toString());
    }

    process.exit();
});
Run Code Online (Sandbox Code Playgroud)

完整的测试程序:

process.on('SIGINT', function() {
    console.log('Naughty SIGINT-handler');
});
process.on('exit', function () {
    console.log('exit');
});
console.log('PID: ', process.pid);

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

process.on('SIGINT', function() {
    console.log('Nice SIGINT-handler');
    var listeners = process.listeners('SIGINT');
    for (var i = 0; i < listeners.length; i++) {
        console.log(listeners[i].toString());
    }

    process.exit();
});
Run Code Online (Sandbox Code Playgroud)

  • 呵呵,非常简单.我有一个关闭服务和流程的SIGINT捕手.我之前必须在代码中有`process.exit`,我想我只是假设它不需要所以我删除了:)谢谢 (4认同)