7

I've found a different post on a related topic (How to perform an async operation on exit), but perhaps it doesn't apply to macOS, or just isn't true anymore when running Node.js v14.

My original question was more complicated. I couldn't get setTimeouts or await to work correctly in a callback (or async callback) for SIGINT. But then I realized what I really needed to do, first and foremost, was to be able to catch and ignore SIGINT.

If I could do that, then I could shutdown in response to SIGINT too, if and when I wanted to.

So I went back to basics to see if I could simply disable SIGINT. I couldn't.

I could detect SIGINT, I could respond with console messages or any other synchronous code, but my code was going to shutdown, and shutdown soon, no matter what I did.

process.on('SIGINT', () => { console.log('here'); return false; });
process.on('SIGINT', () => { console.log('here'); return true; });
process.on('SIGINT', () => { console.log('here'); return undefined; });
process.on('SIGINT', () => { console.log('here'); return new Promise(resolve => { console.log(resolve); }); });

None of these approaches prevents my Node.js server from shutting down after hitting Ctrl+C, or otherwise sending a SIGINT to the process.

UPDATE:

When I run my server via node app.js, SIGINT interception is working just like it should!

Apparently I've been being driven crazy by an artifact of running my server app indirectly through nodemon. A Ctrl+C from my IDE's terminal, or an interrupt sent using the IDE's graphical red (stop) button can't be properly caught, because the resulting signal is really being sent to nodemon. Outside of the IDE environment, however, without nodemon figuring into things, my graceful shutdown works as I want it to.

kshetline
  • 12,547
  • 4
  • 37
  • 73
  • 5
    if anyone reading this is running puppeteer in their node script, be sure to set `handleSIGINT` to `false` when launching the browser: `await puppeteer.launch({ handleSIGINT: false, ...})` cause puppeteer calls process.exit() on SIGINT. – northamerican Dec 08 '21 at 22:40
  • 2
    @northamerican THANK YOU SO MUCH! I just spent 2 hours pulling my hair out and you saved my day. Puppeteer, why the **** are you overriding global behavior like this?!?! – HellaMad May 06 '22 at 10:00

1 Answers1

5

If you observe this kind of unexpected shutdown behavior always think "who is sending what signal?". Depending on the OS and other processes a lot of other signals could be sent, for example see How does SIGINT relate to the other termination signals such as SIGTERM, SIGQUIT and SIGKILL?.

What was most likely happening in your case was that the nodemon process was sending a SIGKILL after the SIGINT. Several such signals exist that cannot be aborted. nodemon allows to control the default termination signal via --signal, see https://github.com/remy/nodemon/blob/master/doc/cli/options.txt. nodemon can also be configured via a local and global config file, see https://github.com/remy/nodemon/blob/master/doc/cli/config.txt.

B M
  • 3,893
  • 3
  • 33
  • 47
  • 1
    I haven't looked into it yet, but I'm hoping there's a way to control the signals nodemon sends. It would be nice if I could tell nodemon to only send SIGINT, or, if it insists on sending SIGKILL, that it at least allow me configure a delay. – kshetline Aug 15 '21 at 20:51
  • 1
    There is indeed. I have added the solution in the response above. If this does not solve your issue another process such as the IDE might be sending the signal. – B M Aug 15 '21 at 21:26