diff --git a/src/index.ts b/src/index.ts index 11dd53abb..777997711 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,13 +14,23 @@ import packageJson from "../package.json"; const jobs: Job[] = []; -process.on("SIGINT", async (_: string, code: number) => { - await cleanupJobResources(jobs); - process.exit(code); -}); +let cleanupAndExitPromise: Promise | null = null; + +async function cleanupAndExit (code: number) { + // First caller's exit code wins — subsequent callers join the in-flight cleanup. + if (cleanupAndExitPromise) return cleanupAndExitPromise; + cleanupAndExitPromise = cleanupJobResources(jobs).finally(() => process.exit(code)); + return cleanupAndExitPromise; +} + +process.on("SIGINT", () => cleanupAndExit(130)); +process.on("SIGTERM", () => cleanupAndExit(143)); +process.on("SIGHUP", () => cleanupAndExit(129)); // Graceful shutdown for nodemon -process.on("SIGUSR2", async () => await cleanupJobResources(jobs)); +process.on("SIGUSR2", async () => { + if (!cleanupAndExitPromise) await cleanupJobResources(jobs); +}); (() => { const yparser = yargs(process.argv.slice(2)); @@ -42,8 +52,7 @@ process.on("SIGUSR2", async () => await cleanupJobResources(jobs)); } else { process.stderr.write(chalk`{red ${e.stack ?? e}}\n`); } - await cleanupJobResources(jobs); - process.exit(1); + await cleanupAndExit(1); } }, builder: (y: any) => { diff --git a/src/job.ts b/src/job.ts index 39b7f72f0..f97ab5354 100644 --- a/src/job.ts +++ b/src/job.ts @@ -772,11 +772,19 @@ If you know what you're doing and would like to suppress this warning, use one o } } + private _cleanupPromise: Promise | null = null; + async cleanupResources () { clearTimeout(this._longRunningSilentTimeout); if (!this.argv.cleanup) return; + if (this._cleanupPromise) return this._cleanupPromise; + this._cleanupPromise = this._doCleanupResources(); + return this._cleanupPromise; + } + + private async _doCleanupResources () { if (this._containersToClean.length > 0) { try { await Utils.spawn([this.argv.containerExecutable, "rm", "-vf", ...this._containersToClean]);