Skip to content

Commit c927fbc

Browse files
authored
Gracefully shutdown task run processes (#2299)
* Gracefully shutdown task run processes * better log, thanks coderabbit
1 parent bf4fff9 commit c927fbc

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

.changeset/early-points-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"trigger.dev": patch
3+
---
4+
5+
Gracefully shutdown task run processes using SIGTERM followed by SIGKILL after a 1s timeout. This also prevents cancelled or completed runs from leaving orphaned Ttask run processes behind

packages/cli-v3/src/executions/taskRunProcess.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export type TaskRunProcessOptions = {
5151
machineResources: MachinePresetResources;
5252
isWarmStart?: boolean;
5353
cwd?: string;
54+
gracefulTerminationTimeoutInMs?: number;
5455
};
5556

5657
export type TaskRunProcessExecuteParams = {
@@ -114,7 +115,7 @@ export class TaskRunProcess {
114115
console.error("Error cancelling task run process", { err });
115116
}
116117

117-
await this.kill();
118+
await this.#gracefullyTerminate(this.options.gracefulTerminationTimeoutInMs);
118119
}
119120

120121
async cleanup(kill = true) {
@@ -131,7 +132,7 @@ export class TaskRunProcess {
131132
}
132133

133134
if (kill) {
134-
await this.kill("SIGKILL");
135+
await this.#gracefullyTerminate(this.options.gracefulTerminationTimeoutInMs);
135136
}
136137
}
137138

@@ -395,6 +396,18 @@ export class TaskRunProcess {
395396
this._stderr.push(errorLine);
396397
}
397398

399+
async #gracefullyTerminate(timeoutInMs: number = 1_000) {
400+
logger.debug("gracefully terminating task run process", { pid: this.pid, timeoutInMs });
401+
402+
await this.kill("SIGTERM", timeoutInMs);
403+
404+
if (this._child?.connected) {
405+
logger.debug("child process is still connected, sending SIGKILL", { pid: this.pid });
406+
407+
await this.kill("SIGKILL");
408+
}
409+
}
410+
398411
/** This will never throw. */
399412
async kill(signal?: number | NodeJS.Signals, timeoutInMs?: number) {
400413
logger.debug(`killing task run process`, {
@@ -420,7 +433,11 @@ export class TaskRunProcess {
420433
const [error] = await tryCatch(killTimeout);
421434

422435
if (error) {
423-
logger.debug("kill: failed to wait for child process to exit", { error });
436+
logger.debug("kill: failed to wait for child process to exit", {
437+
timeoutInMs,
438+
signal,
439+
pid: this.pid,
440+
});
424441
}
425442
}
426443

packages/cli-v3/src/indexing/indexWorkerManifest.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export async function indexWorkerManifest({
6161
}
6262

6363
resolved = true;
64-
child.kill();
64+
child.kill("SIGKILL");
6565
reject(new Error("Worker timed out"));
6666
}, 20_000);
6767

@@ -79,21 +79,21 @@ export async function indexWorkerManifest({
7979
} else {
8080
resolve(message.payload.manifest);
8181
}
82-
child.kill();
82+
child.kill("SIGKILL");
8383
break;
8484
}
8585
case "TASKS_FAILED_TO_PARSE": {
8686
clearTimeout(timeout);
8787
resolved = true;
8888
reject(new TaskMetadataParseError(message.payload.zodIssues, message.payload.tasks));
89-
child.kill();
89+
child.kill("SIGKILL");
9090
break;
9191
}
9292
case "UNCAUGHT_EXCEPTION": {
9393
clearTimeout(timeout);
9494
resolved = true;
9595
reject(new UncaughtExceptionError(message.payload.error, message.payload.origin));
96-
child.kill();
96+
child.kill("SIGKILL");
9797
break;
9898
}
9999
}

0 commit comments

Comments
 (0)