What is the Windows equivalent of process.on('SIGINT') in node.js?
Windowsnode.jsWindows Problem Overview
I'm following the guidance here (listening for SIGINT
events) to gracefully shutdown my Windows-8-hosted node.js application in response to Ctrl+C or server shutdown.
But Windows doesn't have SIGINT
. I also tried process.on('exit')
, but that seems to late to do anything productive.
On Windows, this code gives me: Error: No such module
process.on( 'SIGINT', function() {
console.log( "\ngracefully shutting down from SIGINT (Crtl-C)" )
// wish this worked on Windows
process.exit( )
})
On Windows, this code runs, but is too late to do anything graceful:
process.on( 'exit', function() {
console.log( "never see this log message" )
})
Is there a SIGINT
equivalent event on Windows?
Windows Solutions
Solution 1 - Windows
You have to use the readline module and listen for a SIGINT event:
http://nodejs.org/api/readline.html#readline_event_sigint
if (process.platform === "win32") {
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
rl.on("SIGINT", function () {
process.emit("SIGINT");
});
}
process.on("SIGINT", function () {
//graceful shutdown
process.exit();
});
Solution 2 - Windows
I'm not sure as of when, but on node 8.x and on Windows 10 the original question code simply works now.
process.on( "SIGINT", function() {
console.log( "\ngracefully shutting down from SIGINT (Crtl-C)" );
process.exit();
} );
process.on( "exit", function() {
console.log( "never see this log message" );
} );
setInterval( () => console.log( "tick" ), 2500 );
also works with a windows command prompt.
Solution 3 - Windows
Nowadays it just works on all platforms, including Windows.
The following code logs and then terminates properly on Windows 10:
process.on('SIGINT', () => {
console.log("Terminating...");
process.exit(0);
});
Solution 4 - Windows
Unless you need the "readline" import for other tasks, I would suggest importing "readline" once the program has verified that it's running on Windows. Additionally, for those who might be unaware - this works on both Windows 32-bit and Windows 64-bit systems (which will return the keyword "win32"). Thanks for this solution Gabriel.
if (process.platform === "win32") {
require("readline")
.createInterface({
input: process.stdin,
output: process.stdout
})
.on("SIGINT", function () {
process.emit("SIGINT");
});
}
process.on("SIGINT", function () {
// graceful shutdown
process.exit();
});
Solution 5 - Windows
Currently there is still no support in node for capturing the windows console control events, so there are no equivalents to the POSIX signals:
https://github.com/joyent/node/issues/1553
However the tty module documentation does give an example of a mechanism to capture the key presses in order to initiate a graceful shutdown, but then this does only work for ctrl+c.
var tty = require('tty');
process.stdin.resume();
tty.setRawMode(true);
process.stdin.on('keypress', function(char, key) {
if (key && key.ctrl && key.name == 'c') {
console.log('graceful exit of process %d', process.pid);
process.exit();
}
});
Solution 6 - Windows
Nothing above worked for me, so workaround has been to have a readline hanging and catch the signal from there.
Here my solution:
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
// Flag to be able to force the shutdown
let isShuttingDown = false;
// https://nodejs.org/api/readline.html
rl.on('SIGINT', async () => {
if (isShuttingDown) {
logger.info("Forcing shutdown, bye.");
process.exit();
} else {
if (!<yourIsCleanupNecessaryCheck>()) {
logger.info("No cleanup necessary, bye.");
process.exit();
} else {
logger.info("Closing all opened pages in three seconds (press Ctrl+C again to quit immediately and keep the pages opened) ...");
isShuttingDown = true;
await sleep(3000);
await <yourCleanupLogic>();
logger.info("All pages closed, bye.");
process.exit();
}
}
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
It's quite vanilla, it's asynchronous, and it works both on MacOS 11.3 and Windows 10 (at the time of writing).
Solution 7 - Windows
Since node.js 0.8 the keypress
event no longer exists. There is however an npm package called keypress that reimplements the event.
Install with npm install keypress
, then do something like:
// Windows doesn't use POSIX signals
if (process.platform === "win32") {
const keypress = require("keypress");
keypress(process.stdin);
process.stdin.resume();
process.stdin.setRawMode(true);
process.stdin.setEncoding("utf8");
process.stdin.on("keypress", function(char, key) {
if (key && key.ctrl && key.name == "c") {
// Behave like a SIGUSR2
process.emit("SIGUSR2");
} else if (key && key.ctrl && key.name == "r") {
// Behave like a SIGHUP
process.emit("SIGHUP");
}
});
}
Solution 8 - Windows
Windows + Git Bash/Cygwin solution:
None of the other solutions for Windows and Git Bash worked, so my solution was to simply use WINPTY as follows to launch Node:
My package.json
has this start script:
"start": "winpty node app.js"
This was inspired by the accepted answer here for similar Python issue:
https://stackoverflow.com/questions/50110571/python-error-suppressing-signal-18-to-win32/50120613
Note: WINPTY runs on Windows XP and beyond.