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

与世无争的帅哥 提交于 2021-02-19 01:45:30

问题


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!


回答1:


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



回答2:


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)




回答3:


A cleaner solution would be to wrap the handler for the disconnect in a promise and due to promise internal implementation the resolve will be called only once.

new Promise((resolve) => process.on('SIGINT', resolve))
   .then(() => db.disconnect())
   .then(() => process.exit(0))
   .catch(() => process.exit(1));

Note: I would suggest to avoid calling process.exit() explicitly and let the node to exit by itself. If from some reasons the process didn't exit it means that there is something that blocks it (ex: ports listening, open/pending tcp connections, uncleared setInterval or setTimeout references)



来源:https://stackoverflow.com/questions/54722158/node-and-npm-running-script-and-ctrl-c-triggers-sigint-twice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!