Skip to content

Commit 49c11ca

Browse files
committed
fix: kill ios runner xcodebuild on daemon timeout
1 parent 65bc054 commit 49c11ca

1 file changed

Lines changed: 26 additions & 2 deletions

File tree

src/daemon-client.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import os from 'node:os';
44
import path from 'node:path';
55
import { AppError } from './utils/errors.ts';
66
import type { DaemonRequest as SharedDaemonRequest, DaemonResponse as SharedDaemonResponse } from './daemon/types.ts';
7-
import { runCmdDetached } from './utils/exec.ts';
7+
import { runCmdDetached, runCmdSync } from './utils/exec.ts';
88
import { findProjectRoot, readVersion } from './utils/version.ts';
99
import { createRequestId, emitDiagnostic, withDiagnosticTimer } from './utils/diagnostics.ts';
1010
import {
@@ -41,6 +41,11 @@ const REQUEST_TIMEOUT_MS = resolveDaemonRequestTimeoutMs();
4141
const DAEMON_STARTUP_TIMEOUT_MS = 5000;
4242
const DAEMON_TAKEOVER_TERM_TIMEOUT_MS = 3000;
4343
const DAEMON_TAKEOVER_KILL_TIMEOUT_MS = 1000;
44+
const IOS_RUNNER_XCODEBUILD_KILL_PATTERNS = [
45+
'xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand',
46+
'xcodebuild .*AgentDeviceRunner\\.env\\.session-',
47+
'xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj',
48+
];
4449

4550
export async function sendToDaemon(req: Omit<DaemonRequest, 'token'>): Promise<DaemonResponse> {
4651
const requestId = req.meta?.requestId ?? createRequestId();
@@ -242,20 +247,23 @@ async function sendRequest(info: DaemonInfo, req: DaemonRequest): Promise<Daemon
242247
});
243248
const timeout = setTimeout(() => {
244249
socket.destroy();
250+
const cleanup = cleanupTimedOutIosRunnerBuilds();
245251
emitDiagnostic({
246252
level: 'error',
247253
phase: 'daemon_request_timeout',
248254
data: {
249255
timeoutMs: REQUEST_TIMEOUT_MS,
250256
requestId: req.meta?.requestId,
251257
command: req.command,
258+
timedOutRunnerPidsTerminated: cleanup.terminated,
259+
timedOutRunnerCleanupError: cleanup.error,
252260
},
253261
});
254262
reject(
255263
new AppError('COMMAND_FAILED', 'Daemon request timed out', {
256264
timeoutMs: REQUEST_TIMEOUT_MS,
257265
requestId: req.meta?.requestId,
258-
hint: 'Retry with --debug and check daemon diagnostics logs.',
266+
hint: 'Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected.',
259267
}),
260268
);
261269
}, REQUEST_TIMEOUT_MS);
@@ -307,6 +315,22 @@ async function sendRequest(info: DaemonInfo, req: DaemonRequest): Promise<Daemon
307315
});
308316
}
309317

318+
function cleanupTimedOutIosRunnerBuilds(): { terminated: number; error?: string } {
319+
let terminated = 0;
320+
try {
321+
for (const pattern of IOS_RUNNER_XCODEBUILD_KILL_PATTERNS) {
322+
const result = runCmdSync('pkill', ['-f', pattern], { allowFailure: true });
323+
if (result.exitCode === 0) terminated += 1;
324+
}
325+
return { terminated };
326+
} catch (error) {
327+
return {
328+
terminated,
329+
error: error instanceof Error ? error.message : String(error),
330+
};
331+
}
332+
}
333+
310334
export function resolveDaemonRequestTimeoutMs(raw: string | undefined = process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS): number {
311335
if (!raw) return 90000;
312336
const parsed = Number(raw);

0 commit comments

Comments
 (0)