From 50703f8ae61c51c899f944f6f76b535925a6b9eb Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Thu, 16 Feb 2023 01:52:42 +0100 Subject: [PATCH] Treat unhandled errors as fatal All possible Promise rejections and exception bubbling should be handled by either the code creating the exception or the code invoking the operation that could fail. Treat therefore uncaught exceptions and unhandled promise rejetions as fatal errors that log a traceback and immedately terminate the Node.js process. --- packages/ctl/ctl.js | 1 + packages/lib/logging_utils.js | 14 ++++++++++++++ packages/master/master.js | 4 +--- packages/slave/slave.js | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/ctl/ctl.js b/packages/ctl/ctl.js index 8b767ae9..62ffd2bd 100755 --- a/packages/ctl/ctl.js +++ b/packages/ctl/ctl.js @@ -187,6 +187,7 @@ async function startControl() { level: args.logLevel, format: new libLoggingUtils.TerminalFormat(), })); + libLoggingUtils.handleUnhandledErrors(logger); logger.verbose(`Loading available plugins from ${args.pluginList}`); let pluginList = new Map(); diff --git a/packages/lib/logging_utils.js b/packages/lib/logging_utils.js index 0451f56e..5117a421 100644 --- a/packages/lib/logging_utils.js +++ b/packages/lib/logging_utils.js @@ -458,11 +458,25 @@ async function migrateLogs(log, directory, pattern) { } } +function handleUnhandledErrors() { + /* eslint-disable node/no-process-exit */ + process.on("uncaughtException", err => { + logger.fatal(`Uncaught exception:\n${err.stack}`); + process.exit(1); + }); + process.on("unhandledRejection", (reason, promise) => { + logger.fatal(`Unhandled rejection:\n${reason.stack ? reason.stack : reason}`); + process.exit(1); + }); + /* eslint-enable node/no-process-exit */ +} + module.exports = { TerminalFormat, LinkTransport, LogIndex, + handleUnhandledErrors, queryLog, migrateLogs, diff --git a/packages/master/master.js b/packages/master/master.js index 59bd8317..b1a21cc9 100755 --- a/packages/master/master.js +++ b/packages/master/master.js @@ -284,6 +284,7 @@ async function initialize() { format: new libLoggingUtils.TerminalFormat(), })); } + libLoggingUtils.handleUnhandledErrors(logger); let command = parameters.args._[0]; if (command === "run") { @@ -355,9 +356,6 @@ async function startup() { // and as the process name in ps/top on linux. process.title = "clusterioMaster"; - // add better stack traces on promise rejection - process.on("unhandledRejection", err => logger.error(`Unhandled rejection:\n${err.stack}`)); - let { args, shouldRun, clusterLogger, pluginInfos, masterConfigPath, masterConfig } = await initialize(); if (!shouldRun) { return; diff --git a/packages/slave/slave.js b/packages/slave/slave.js index ac0cf4b8..d52a3d00 100755 --- a/packages/slave/slave.js +++ b/packages/slave/slave.js @@ -129,6 +129,7 @@ async function startSlave() { filter: info => info.instance_id === undefined, })); } + libLoggingUtils.handleUnhandledErrors(logger); let command = args._[0]; if (command === "run") {