From 0383c24087cd81e6fc98fce06e3e427d61c66dc5 Mon Sep 17 00:00:00 2001 From: Joe Duffy Date: Mon, 30 Oct 2017 11:48:54 -0700 Subject: [PATCH] Drain the message queue before exiting (#498) This change remembers that we failed due to an uncaught exception, and defers the process.exit(1) until we actually reach the process's exit event. This ensures that we drain the message queue before exiting, which ensures that outbound messages actually reach their destination. --- sdk/nodejs/cmd/run/index.ts | 19 ++++++++++++++----- sdk/nodejs/runtime/settings.ts | 17 +++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/sdk/nodejs/cmd/run/index.ts b/sdk/nodejs/cmd/run/index.ts index 44649d7a7..c04779579 100644 --- a/sdk/nodejs/cmd/run/index.ts +++ b/sdk/nodejs/cmd/run/index.ts @@ -125,6 +125,7 @@ export function main(args: string[]): void { process.argv = [ process.argv[0], process.argv[1], ...programArgs ]; // Set up the process unhandled exception handler and the program exit handler. + let uncaught: Error | undefined; process.on("uncaughtException", (err: Error) => { // First, log the error. if (err instanceof RunError) { @@ -133,14 +134,22 @@ export function main(args: string[]): void { log.error(err.message); } else { - console.log(`Running program '${program}' failed with an unhandled exception:`); - console.log(err); + log.error(`Running program '${program}' failed with an unhandled exception:`); + log.error(err.toString()); } - // And next, exit with a non-zero exit code. - process.exit(1); + + // Remember that we failed with an error. Don't quit just yet so we have a chance to drain the message loop. + uncaught = err; }); - process.on("exit", () => { runtime.disconnectSync(); }); + process.on("exit", (code: number) => { + runtime.disconnectSync(); + + // If we don't already have an exit code, and we had an unhandled error, exit with a non-success. + if (code === 0 && uncaught) { + process.exit(1); + } + }); // Now go ahead and execute the code. The process will remain alive until the message loop empties. log.debug(`Running program '${program}' in pwd '${process.cwd()}' w/ args: ${programArgs}`); diff --git a/sdk/nodejs/runtime/settings.ts b/sdk/nodejs/runtime/settings.ts index c949d4b24..8db00742c 100644 --- a/sdk/nodejs/runtime/settings.ts +++ b/sdk/nodejs/runtime/settings.ts @@ -101,13 +101,18 @@ export function disconnect(): void { */ export function disconnectSync(): void { // Otherwise, actually perform the close activities. - if (options.monitor) { - (options.monitor).close(); - (options).monitor = null; + try { + if (options.monitor) { + (options.monitor).close(); + (options).monitor = null; + } + if (options.engine) { + (options.engine).close(); + (options).engine = null; + } } - if (options.engine) { - (options.engine).close(); - (options).engine = null; + catch (err) { + // ignore all failures to avoid crashes during exit. } }