diff --git a/settings.json.docker b/settings.json.docker index 7bb2917c2..228c70d2a 100644 --- a/settings.json.docker +++ b/settings.json.docker @@ -463,6 +463,11 @@ */ "loadTest": "${LOAD_TEST:false}", + /** + * Disable dump of objects preventing a clean exit + */ + "dumpOnUncleanExit": false, + /* * Disable indentation on new line when previous line ends with some special * chars (':', '[', '(', '{') diff --git a/settings.json.template b/settings.json.template index b8722fbdc..8a676b56d 100644 --- a/settings.json.template +++ b/settings.json.template @@ -468,6 +468,11 @@ */ "loadTest": false, + /** + * Disable dump of objects preventing a clean exit + */ + "dumpOnUncleanExit": false, + /* * Disable indentation on new line when previous line ends with some special * chars (':', '[', '(', '{') diff --git a/src/node/server.js b/src/node/server.js index a574116eb..f895df2af 100755 --- a/src/node/server.js +++ b/src/node/server.js @@ -27,9 +27,14 @@ const log4js = require('log4js'); log4js.replaceConsole(); -// wtfnode should be loaded after log4js.replaceConsole() so that it uses log4js for logging, and it -// should be above everything else so that it can hook in before resources are used. -const wtfnode = require('wtfnode'); +const settings = require('./utils/Settings'); + +let wtfnode; +if (settings.dumpOnUncleanExit) { + // wtfnode should be loaded after log4js.replaceConsole() so that it uses log4js for logging, and + // it should be above everything else so that it can hook in before resources are used. + wtfnode = require('wtfnode'); +} /* * early check for version compatibility before calling @@ -45,7 +50,6 @@ const express = require('./hooks/express'); const hooks = require('../static/js/pluginfw/hooks'); const pluginDefs = require('../static/js/pluginfw/plugin_defs'); const plugins = require('../static/js/pluginfw/plugins'); -const settings = require('./utils/Settings'); const stats = require('./stats'); const logger = log4js.getLogger('server'); @@ -248,16 +252,25 @@ exports.exit = async (err = null) => { exitGate = new Gate(); state = State.EXITING; exitGate.resolve(); + // Node.js should exit on its own without further action. Add a timeout to force Node.js to exit - // just in case something failed to get cleaned up during the shutdown hook. unref() is called on - // the timeout so that the timeout itself does not prevent Node.js from exiting. + // just in case something failed to get cleaned up during the shutdown hook. unref() is called + // on the timeout so that the timeout itself does not prevent Node.js from exiting. setTimeout(() => { logger.error('Something that should have been cleaned up during the shutdown hook (such as ' + - 'a timer, worker thread, or open connection) is preventing Node.js from exiting'); - wtfnode.dump(); + 'a timer, worker thread, or open connection) is preventing Node.js from exiting'); + + if (settings.dumpOnUncleanExit) { + wtfnode.dump(); + } else { + logger.error('Enable `dumpOnUncleanExit` setting to get a dump of objects preventing a ' + + 'clean exit'); + } + logger.error('Forcing an unclean exit...'); process.exit(1); }, 5000).unref(); + logger.info('Waiting for Node.js to exit...'); state = State.WAITING_FOR_EXIT; /* eslint-enable no-process-exit */ diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 0333f7972..60f4e6442 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -250,6 +250,11 @@ exports.automaticReconnectionTimeout = 0; */ exports.loadTest = false; +/** + * Disable dump of objects preventing a clean exit + */ +exports.dumpOnUncleanExit = false; + /** * Enable indentation on new lines */