Nodejs - process hangs on exit (Ctrl+C)

前端 未结 1 1903
孤城傲影
孤城傲影 2020-12-31 02:29

I have a node.js project which does many things, it spawns child processes, it opens an http and socket.io server, etc..

When I run it from the console, closing it w

相关标签:
1条回答
  • 2020-12-31 02:57

    Scripts are themselves responsible for properly shutting down once they listen to the SIGINT event, as the default handler (killing the process) is disabled then.

    Check out this example program:

    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/');
    

    Execute it and then try killing it: It won't work. The SIGINT signal will always get passed to your custom build signal handler. In order to properly shut the process down you will have to manually call 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/');
    

    process.exit() will:

    1. Set some internal flags
    2. Call the process.on('exit') handlers
    3. Call process.reallyExit
    4. Which will call the C++ exit() function, therefore process.exit() is final and will cause a shutdown (unless you block execution by an endless loop in your on('exit') handler).

    Long story short: Your code probably listens to SIGINT somewhere. You can fetch a list of those listeners via:

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

    You can even pretty print them on the console:

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

    Using the information I gave above you can easily compile yet another SIGINT-handler that will list all the handlers and then cleanly exit the process, hopefully leading your path to the naughty ones:

    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();
    });
    

    Complete program for testing:

    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();
    });
    
    0 讨论(0)
提交回复
热议问题