Search code examples
node.jsmongodbexpressapplication-shutdown

Express.js app not shutting down cleanly with server.close()


I'm trying to properly close a MongoDB connection when the app is shut down. Here is the code:

var express = require('express')
  , http = require('http')
  , mongoose = require('mongoose')
  , path = require('path');

var app = express();

app.set('port', process.env.PORT || 3000);

mongoose.connect('mongodb://localhost/test');

// some post and get handlers etc. (removed for shorter output)

var server = app.listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

function cleanup () {
    server.close(function () {
        console.log("Closed out remaining connections.");
        mongoose.connection.close();
        process.exit();
    });

    setTimeout( function () {
        console.error("Could not close connections in time, forcing shut down");
        process.exit(1);
    }, 30*1000);
}

process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);

All is well and works when the app starts for the first time. When I hit Ctrl-c right after it has started, it cleanly shuts down with the Closed out remaining connections. message. However, as soon as the app interacts with the database or even serves a static page, and I try to shut it down after that, it exits with the following error:

net.js:1225
    throw new Error('Not running');
          ^
Error: Not running
    at Server.close (net.js:1225:11)
    at process.cleanup (<...>/app.js:77:12)
    at process.EventEmitter.emit (events.js:92:17)
    at Signal.wrap.onsignal (node.js:756:46)
22 Aug 15:15:28 - [nodemon] exiting

Any ideas what is causing this error and how I could fix it?


Solution

  • When server.close is called, there are two properties that are checked.

       handle<tcp handle>
       connections
    

    Responsible code fragment of server.close responsible for this error;

      if (!this._handle) {
        // Throw error. Follows net_legacy behaviour.
        throw new Error('Not running');
      }
    

    Only if handle===null and connections ===0 that the callback passed to close is called.

    Case : Server is started and sent the signal with no serving.

    Before close is called;

      handle === TCP handle.
      connection===0;
    

    After close handle===null; connection===0;

    The callback gets called.

    Case : Server is started and sent the signal after a request server.

    Before close is called;

      handle === TCP.handle;
      connection===1;
    

    After close handle === null; connection===1;

    No callback is fired.

    Second time when you press ctrl-c

    Before close is called;

      handle === null;
      connection===1;
    

    since handle===null , the check throws the error you are seeing.