Merge pull request #719 from pulumi/UnhandledPromiseRejection
Treat unhandled promise rejections as uncaught exceptions.
This commit is contained in:
commit
f449db974d
|
@ -118,9 +118,9 @@ export function main(args: string[]): void {
|
||||||
const programArgs: string[] = argv._.slice(1);
|
const programArgs: string[] = argv._.slice(1);
|
||||||
process.argv = [ process.argv[0], process.argv[1], ...programArgs ];
|
process.argv = [ process.argv[0], process.argv[1], ...programArgs ];
|
||||||
|
|
||||||
// Set up the process unhandled exception handler and the program exit handler.
|
// Set up the process uncaught exception, unhandled rejection, and program exit handlers.
|
||||||
let uncaught: Error | undefined;
|
let uncaught: Error | undefined;
|
||||||
process.on("uncaughtException", (err: Error) => {
|
const uncaughtHandler = (err: Error) => {
|
||||||
// First, log the error.
|
// First, log the error.
|
||||||
if (err instanceof RunError) {
|
if (err instanceof RunError) {
|
||||||
// For errors that are subtypes of RunError, we will print the message without hitting the unhandled error
|
// For errors that are subtypes of RunError, we will print the message without hitting the unhandled error
|
||||||
|
@ -134,7 +134,9 @@ export function main(args: string[]): void {
|
||||||
|
|
||||||
// Remember that we failed with an error. Don't quit just yet so we have a chance to drain the message loop.
|
// Remember that we failed with an error. Don't quit just yet so we have a chance to drain the message loop.
|
||||||
uncaught = err;
|
uncaught = err;
|
||||||
});
|
};
|
||||||
|
process.on("uncaughtException", uncaughtHandler);
|
||||||
|
process.on("unhandledRejection", uncaughtHandler);
|
||||||
|
|
||||||
process.on("exit", (code: number) => {
|
process.on("exit", (code: number) => {
|
||||||
runtime.disconnectSync();
|
runtime.disconnectSync();
|
||||||
|
|
|
@ -22,10 +22,6 @@ let leakDetectorScheduled: boolean = false;
|
||||||
* leakCandidates tracks the list of potential leak candidates.
|
* leakCandidates tracks the list of potential leak candidates.
|
||||||
*/
|
*/
|
||||||
const leakCandidates: Set<Promise<any>> = new Set<Promise<any>>();
|
const leakCandidates: Set<Promise<any>> = new Set<Promise<any>>();
|
||||||
/**
|
|
||||||
* unhandledHandlerScheduled is true when the unhandled promise detector is scheduled for this process.
|
|
||||||
*/
|
|
||||||
let unhandledHandlerScheduled: boolean = false;
|
|
||||||
|
|
||||||
function promiseDebugString(p: Promise<any>): string {
|
function promiseDebugString(p: Promise<any>): string {
|
||||||
return `CONTEXT: ${(<any>p)._debugCtx}\n` +
|
return `CONTEXT: ${(<any>p)._debugCtx}\n` +
|
||||||
|
@ -41,19 +37,6 @@ export function debuggablePromise<T>(p: Promise<T>, ctx?: any): Promise<T> {
|
||||||
(<any>p)._debugCtx = ctx;
|
(<any>p)._debugCtx = ctx;
|
||||||
(<any>p)._debugStackTrace = new Error().stack;
|
(<any>p)._debugStackTrace = new Error().stack;
|
||||||
|
|
||||||
// If the unhandled handler isn't active yet, schedule it.
|
|
||||||
if (!unhandledHandlerScheduled) {
|
|
||||||
process.on("unhandledRejection", (reason, innerPromise) => {
|
|
||||||
if (!log.hasErrors()) {
|
|
||||||
console.error("Unhandled promise rejection:");
|
|
||||||
console.error(reason);
|
|
||||||
console.error(reason.stack);
|
|
||||||
console.error(promiseDebugString(innerPromise));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
unhandledHandlerScheduled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugPromiseLeaks) {
|
if (debugPromiseLeaks) {
|
||||||
// Setup leak detection.
|
// Setup leak detection.
|
||||||
if (!leakDetectorScheduled) {
|
if (!leakDetectorScheduled) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
throw new Error("💥 goes the dynamite");
|
throw new Error("💥 goes the dynamite");
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
reject(new Error("💥 goes the dynamite (as promised)"));
|
||||||
|
});
|
|
@ -310,6 +310,12 @@ describe("rpc", () => {
|
||||||
return { urn: makeUrn(t, name), id: undefined, props: res };
|
return { urn: makeUrn(t, name), id: undefined, props: res };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// A program that contains an unhandled promise rejection.
|
||||||
|
"unhandled_promise_rejection": {
|
||||||
|
program: path.join(base, "013.unhandled_promise_rejection"),
|
||||||
|
expectResourceCount: 0,
|
||||||
|
expectError: "Program exited with non-zero exit code: 1",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const casename of Object.keys(cases)) {
|
for (const casename of Object.keys(cases)) {
|
||||||
|
|
Loading…
Reference in a new issue