3

My code:

process.on('SIGINT', function() {
  console.log('Interrupted');
  process.exit();
});

// A big loop here that takes several seconds to execute through.

console.log('Exited without interruption');

I run the program from the command line, and while it is still running, press ctrl+C. I am immediately returned to the command line. However, the console.log('Interrupted') does not display in the output. After some time elapses, the console.log('Exited without interruption') is displayed, proving that the process did not exit when I hit ctrl+C, but instead kept running in the background after I was returned to the command line.

Removing the process.on() statement allows the process to exit when ctrl+C is pressed. (No 'Exited without interruption' is output.)

Have tried both the () => { and function() { function declaration styles with same result.

Mods, please do not too hastily mark this as a duplicate, although of course, I'm happy to be referred to an existing solution that works. I've seen Can't stop local node server with Ctrl + C (Mac) - the behavior in response to ctrl+C is different.

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
Erik Hermansen
  • 2,200
  • 3
  • 21
  • 41
  • Can you try either `() = >` or `function(signal) ` function definitions? I feel like there was some small change along those lines I had to make for a similar problem. –  Mar 23 '18 at 20:28
  • Yeah, I've tried both with same results. Thanks for the suggestion. Will update my question to indicate I've tried that. – Erik Hermansen Mar 23 '18 at 20:33
  • Does the expected behavior (no 'Exited without interruption') occur with an empty function? –  Mar 23 '18 at 20:35
  • No difference. The ctrl+c edit I made was automatically suggested by SO, and I thought it looked snazzy. – Erik Hermansen Mar 23 '18 at 20:50
  • Re "Does the expected behavior occur with an empty function?" Yes, the behavior is the same whether the handler function is an empty block or contains the above handling code. – Erik Hermansen Mar 23 '18 at 20:53

1 Answers1

8
// Begin reading from stdin so the process does not exit imidiately
process.stdin.resume();
process.on('SIGINT', function() {
  console.log('Interrupted');
  process.exit();
});

https://nodejs.org/api/process.html#process_signal_events

EDIT:

// A big loop here that takes several seconds to execute through.

This is your problem. NodeJS is single-tread. When you perform sync loop you blocks event-loop and other event listeners wont be able work at the same time.

You can:

  1. Make loop async (recursive function with process.nextTick())
  2. Spawn child-process (worker) for loop job, then main event-loop will wont be blocked
Artur P.
  • 886
  • 4
  • 12
  • Tried it, thanks. Doesn't change behavior. Note there is no issue with the process exiting too soon. – Erik Hermansen Mar 23 '18 at 20:57
  • Maybe this is the problem: SIGINT from the terminal is supported on all platforms, and can usually be generated with +C (though this may be configurable). It is not generated when terminal raw mode is enabled. – Artur P. Mar 23 '18 at 20:58
  • let me revise my observation above. By adding the stdin.resume() I can see something new happening. The 'interrupted' text will display but only AFTER the lengthy loop finished. At that point, it is necessary to press a key, and then I'm returned to the command line. So with the above code, the handler will run, but it will not run immediately after ctrl+c is pressed, and ctrl+c will not stop the process. – Erik Hermansen Mar 23 '18 at 21:02
  • 1
    Yes, this was the problem. Sorry for the long wait before replying--I went on vacation. I resolved the problem by structuring the work as a promise chain--in other words, make the loop async, as you suggested. – Erik Hermansen Apr 10 '18 at 19:41
  • This ended up working for me on Ubuntu 20.04 through WSL. Turns out I 100% missed that line `process.stdin.resume()` on the documentation. Oops! – Kayden van Rijn Jun 15 '23 at 17:26