Skip to content

Commit

Permalink
Different uncaughtException handling (#4511)
Browse files Browse the repository at this point in the history
* Different uncaughtException handling

We've seen some uncaught exceptions where the process exits before logs are apparently flushed. This hopefully addresses that. Also start up sentry earlier, and catch top level exits differently.

With ref to winstonjs/winston#1504 (comment) and https://nodejs.org/api/process.html#event-uncaughtexception
  • Loading branch information
mattgodbolt committed Jan 24, 2023
1 parent 6f0d746 commit 17389aa
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions app.js
Expand Up @@ -453,6 +453,11 @@ const awsProps = props.propsFor('aws');
// eslint-disable-next-line max-statements
async function main() {
await aws.initConfig(awsProps);
// Initialise express and then sentry. Sentry as early as possible to catch errors during startup.
const webServer = express(),
router = express.Router();
setupSentry(aws.getConfig('sentryDsn'));

startWineInit();

const clientOptionsHandler = new ClientOptionsHandler(sources, compilerProps, defArgs);
Expand Down Expand Up @@ -505,9 +510,6 @@ async function main() {
process.exit(0);
}

const webServer = express(),
router = express.Router();
setupSentry(aws.getConfig('sentryDsn'));
const healthCheckFilePath = ceProps('healthCheckFilePath', false);

const handlerConfig = {
Expand Down Expand Up @@ -818,24 +820,29 @@ if (opts.version) {
process.exit(0);
}

process.on('uncaughtException', terminationHandler('uncaughtException', 1));
process.on('SIGINT', terminationHandler('SIGINT', 0));
process.on('SIGTERM', terminationHandler('SIGTERM', 0));
process.on('SIGQUIT', terminationHandler('SIGQUIT', 0));
process.on('uncaughtException', uncaughtHandler);
process.on('SIGINT', signalHandler('SIGINT'));
process.on('SIGTERM', signalHandler('SIGTERM'));
process.on('SIGQUIT', signalHandler('SIGQUIT'));

function terminationHandler(name, code) {
return error => {
function signalHandler(name) {
return () => {
logger.info(`stopping process: ${name}`);
if (error && error instanceof Error) {
logger.error(error);
}
process.exit(code);
process.exit(0);
};
}

function uncaughtHandler(err, origin) {
logger.info(`stopping process: Uncaught exception: ${err}\nException origin: ${origin}`);
// The app will exit naturally from here, but if we call `process.exit()` we may lose log lines.
// see https://github.com/winstonjs/winston/issues/1504#issuecomment-1033087411
process.exitCode = 1;
}

// Once we move to modules, we can remove this and use a top level await.
// eslint-disable-next-line unicorn/prefer-top-level-await
main().catch(err => {
logger.error('Top-level error (shutting down):', err);
process.exit(1);
// Shut down after a second to hopefully let logs flush.
setTimeout(() => process.exit(1), 1000);
});

0 comments on commit 17389aa

Please sign in to comment.