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. } }