Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node and NPM Running script and Ctrl-C triggers SIGINT twice

I've come across a problem on one of my Nodejs apps running with npm start (which just does node app.js).

My app contains a sigint handler as follows:

process.on('SIGINT', () => {
    db.disconnect().then({
        process.exit(0);
    }).catch(e => process.exit(1));
});

With corresponding logs. After some testing on other files, I've noticed that Ctrl-C when on an npm process triggers SIGINT twice if the first one takes too long to exit. (try adding a timeout on a sample app).

For now I've added a counter to check if the call is performed more than once, but I'm not sure that's "the way to go" concerning this issue. I'm guessing that a SIGINT on an npm process is expected to quit in a certain timeframe, which is why npm passes it on one more time (always only twice).

Has anyone come across this problem and found a viable solution?

Thanks!

like image 702
Jo Colina Avatar asked Feb 16 '19 10:02

Jo Colina


2 Answers

I know this post has been around for a while but unfortunately I'm getting the same issue. When running just node <app.js> it fires just one signal. That signal comes twice if running npm start. Instead a counter, I suggest check if the server is still listening, if yes, proceed with your logic and internal termination (like db connections etc):

process.on('SIGINT', function(){
 if (server.listening) {
    server.close(function (err) {
      if (err) {
        console.error(err);
        process.exit(1)
      }
      process.exit(0);
    })
 }
})
like image 179
David Aleixo Avatar answered Sep 19 '22 17:09

David Aleixo


You might want to run your command's directly via node, rather than via npm start. NPM can be a cause for wierd trapping of signals, see https://lisk.io/blog/tutorial/why-we-stopped-using-npm-start-child-processes.

Your SIGINT handler can get called multiple times, you should write your code to protect against that.

Also if you are running parent/child processes, see https://github.com/jtlapp/node-cleanup

When you hit Ctrl-C, you send a SIGINT signal to each process in the current process group. A process group is set of processes that are all supposed to end together as a group instead of persisting independently. However, some programs, such as Emacs, intercept and repurpose SIGINT so that it does not end the process. In such cases, SIGINT should not end any processes of the group.

Additionally, calling process.exit is not necessary most of the time, see https://nodejs.org/api/process.html#process_process_exit_code

Instead set process.exitCode, remove your signal handlers and then re-raise the signal via process.kill(process.pid, signal)

like image 30
Bae Avatar answered Sep 17 '22 17:09

Bae