I need to do some useful things when my Express.js service is stopped by SIGINT
. Using Express.js version 3.0.6, I understand that this should work:
var express = require('express');
var app = express();
var server = app.listen(3000);
process.on('SIGINT', function() {
console.log('Do something useful here.');
server.close();
});
But the process doesn't give me back the Bash prompt unless I issue SIGINT
(Control-C) twice:
$ node problem.js
^CDo something useful here.
^CDo something useful here.
net.js:1046
throw new Error('Not running');
^
Error: Not running
at Server.close (net.js:1046:11)
at process.<anonymous> (/path/to/problem.js:8:10)
at process.EventEmitter.emit (events.js:93:17)
at SignalWatcher.startup.processSignalHandlers.process.on.process.addListener.w.callback (node.js:486:45)
$
One more caveat. If I start this Express.js service and don't send any requests then SIGINT
terminates properly.
Clearly there is something fundamental that I'm missing here?
Here compression means the gzip compression on the express server. You can use the compression middleware to add easy gzip compression to your server.
The SIGINT signal is sent to a process by its controlling terminal when a user wishes to interrupt the process. This is typically initiated by pressing Ctrl+C . The SIGTERM signal is sent to a process to request its termination. Unlike the SIGKILL signal, it can be caught and interpreted or ignored by the process.
Express JS is minimal and unopinionatedExpress uses less overhead in the core framework so that makes it minimal and a good choice for building out large web applications. You don't want to have a framework that fills your codebase with lots of bloatware that you are never gonna use.
Fastify provides full encapsulation for plug-ins, automatically parses JSON with relatively faster rendering, and provides quick routing. Among other benefits, Fastify also has a cleaner syntax for writing async code in controllers. Express, however, has a stronger user base with plenty of documentation available.
By catching the SIGINT
handler, you are preventing the default behaviour, which is to quit the process. When you use Ctrl+C
the second time, the process dies because server.close
throws an uncaught exception.
Just add a process.exit()
to the end of your SIGINT
handler to quit the process gracefully.
Resurrecting an oldie since the question is not completely (or correctly) answered and people might still find this answer.
The important part of your question is:
One more caveat. If I start this Express.js service and don't send any requests then SIGINT terminates properly. Clearly there is something fundamental that I'm missing here?`
What you are missing is that by default express keeps connections open (HTTP keep-alive) for re-use. So, when there has been a (recent) request there's still something on the event-loop and that's the reason your app is not closing.
Using process.exit()
will work, but is like sending another ^C, and may hide the fact that there is still something else open (e.g. database connections). Your app should just close when there's nothing left on the event-loop.
So, I modified your example, setting a 5 second keep-alive on the connection so it will graceful shutdown in a reasonable time.
var express = require('express');
var serverPort = 3000;
var app = express();
var server = app.listen(serverPort);
// HTTP Keep-Alive to a short time to allow graceful shutdown
server.on('connection', function (socket) {
socket.setTimeout(5 * 1000);
});
// Handle ^C
process.on('SIGINT', shutdown);
// Do graceful shutdown
function shutdown() {
console.log('graceful shutdown express');
server.close(function () {
console.log('closed express');
});
}
console.log('running server: http://localhost:' + serverPort);
I am using this code:
server.close(() => {
process.exit(0)
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With