关于node.js:Nodejs-进程在退出时挂起(Ctrl + C)

Nodejs - process hangs on exit (Ctrl+C)

我有一个node.js项目,它执行许多操作,它产生子进程,打开一个http和socket.io服务器,等等。

当我从控制台运行它时,用Ctrl+C关闭它,它只是挂起。
从webstorm来看,停止该过程分为两个步骤,首先单击Stop,然后再次单击该按钮,仅第二次该按钮是一个头骨图标。

现在,我知道它留下了一些悬而未决的东西,但是我无法弄清楚是什么,我试图跟踪所有启动过程的地方,并确保已正确杀死它们。

有没有一种方法可以调试它并找出导致我的进程挂起的原因? 难道是日志记录打开了写流,并且永远不会关闭? 我什至不知道什么样的事情会使一个进程挂在SIGINT上。

编辑:我已经下载了pstree,以查看主进程产生的任何子进程是否仍然存在。 看来它们都正确终止了-仅剩下主节点进程了。


脚本本身负责在监听SIGINT事件后正确关闭,因为默认的处理程序(杀死进程)随后被禁用。

查看以下示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
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\
');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

执行它,然后尝试将其杀死:它不起作用。 SIGINT信号将始终传递到您的自定义生成信号处理程序。为了正确关闭进程,您将必须手动调用process.exit()

1
2
3
4
5
6
7
8
9
10
11
12
13
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\
');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

process.exit()将:

  • 设置一些内部标志
  • 调用process.on('exit')处理程序
  • 致电process.reallyExit
  • 它将调用C ++ exit()函数,因此process.exit()是最终的,并且将导致关机(除非您通过on('exit')处理程序中的无限循环来阻止执行)。
  • 长话短说:您的代码可能在某处监听了SIGINT。您可以通过以下方式获取这些侦听器的列表:

    1
    var listeners = process.listeners('SIGINT');

    您甚至可以在控制台上漂亮地打印它们:

    1
    2
    3
    for (var i = 0; i < listeners.length; i++) {
        console.log(listeners[i].toString());
    }

    使用我在上面提供的信息,您可以轻松地编译另一个SIGINT -handler,该处理器将列出所有处理程序,然后干净地退出该过程,希望将您的方法引向顽皮的程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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();
    });

    完整的测试程序:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    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\
    ');
    }).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();
    });