Skip to content

Commit 6a232a9

Browse files
authored
Prevent hanging processes from preventing container cleanup (RooCodeInc#4428)
1 parent b6bfeef commit 6a232a9

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

packages/evals/src/cli/runTask.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ import { exercisesPath } from "../exercises/index.js"
2020

2121
import { getTag, isDockerContainer } from "./utils.js"
2222

23+
class SubprocessTimeoutError extends Error {
24+
constructor(timeout: number) {
25+
super(`Subprocess timeout after ${timeout}ms`)
26+
this.name = "SubprocessTimeoutError"
27+
}
28+
}
29+
2330
type RunTaskOptions = {
2431
run: Run
2532
task: Task
@@ -196,7 +203,9 @@ export const runTask = async ({ run, task, publish }: RunTaskOptions) => {
196203
await updateTask(task.id, { finishedAt: new Date() })
197204
}
198205

199-
if (!isClientDisconnected) {
206+
if (isClientDisconnected) {
207+
logError("client disconnected before task finished")
208+
} else {
200209
if (rooTaskId) {
201210
log("closing task")
202211
client.sendCommand({ commandName: TaskCommandName.CloseTask, data: rooTaskId })
@@ -206,6 +215,36 @@ export const runTask = async ({ run, task, publish }: RunTaskOptions) => {
206215
client.disconnect()
207216
}
208217

218+
log("waiting for subprocess to finish")
209219
controller.abort()
210-
await subprocess
220+
221+
// Wait for subprocess to finish gracefully, with a timeout.
222+
const SUBPROCESS_TIMEOUT = 10_000
223+
224+
try {
225+
await Promise.race([
226+
subprocess,
227+
new Promise((_, reject) =>
228+
setTimeout(() => reject(new SubprocessTimeoutError(SUBPROCESS_TIMEOUT)), SUBPROCESS_TIMEOUT),
229+
),
230+
])
231+
232+
log("subprocess finished gracefully")
233+
} catch (error) {
234+
if (error instanceof SubprocessTimeoutError) {
235+
logError("subprocess did not finish within timeout, force killing")
236+
237+
try {
238+
if (subprocess.kill("SIGKILL")) {
239+
log("SIGKILL sent to subprocess")
240+
} else {
241+
logError("failed to send SIGKILL to subprocess")
242+
}
243+
} catch (killError) {
244+
logError("subprocess.kill(SIGKILL) failed:", killError)
245+
}
246+
} else {
247+
throw error
248+
}
249+
}
211250
}

0 commit comments

Comments
 (0)