Fix SIGKILL fallback bug in timeout handling

- Replace unreliable process.killed check with signal 0 test
- Use try-catch around all process.kill() calls
- Properly detect if process is still running before SIGKILL
- Fixes bug where SIGKILL was never sent to stuck processes

The process.killed property is set immediately when process.kill()
is called, regardless of actual process termination. Using signal 0
to test process existence is the correct approach.
This commit is contained in:
codegen-sh[bot] 2025-06-08 04:40:56 +00:00
parent b80cceb541
commit fe9599819c

View file

@ -139,28 +139,35 @@ export async function executeSwiftCli(
const timeoutId = setTimeout(() => {
if (!isResolved) {
isResolved = true;
logger.error(
{ timeoutMs, command: cliPath, args: fullArgs },
"Swift CLI execution timed out"
);
// Kill the process
process.kill('SIGTERM');
// Kill the process with SIGTERM first
try {
try {
process.kill('SIGTERM');
} catch (err) {
// Process might already be dead
}
} catch (err) {
// Process might already be dead
}
// Give it a moment to terminate gracefully, then force kill
setTimeout(() => {
if (!process.killed) {
try {
// Check if process is still running by trying to send signal 0
process.kill(0);
// If we get here, process is still alive, so force kill it
process.kill('SIGKILL');
} catch (err) {
// Process is already dead, which is what we want
} catch (err) {
// Process is already dead, which is what we want
}
}, 1000);
resolve({
success: false,
error: {
message: `Swift CLI execution timed out after ${timeoutMs}ms. This may indicate a permission dialog is waiting for user input, or the process is stuck.`,
code: "SWIFT_CLI_TIMEOUT",
details: `Command: ${cliPath} ${fullArgs.join(' ')}`,
},
resolve({
success: false,
error: `Command timed out after ${timeoutMs}ms: ${cliPath} ${args.join(' ')}`
});
}
}, timeoutMs);
@ -356,12 +363,21 @@ export async function execPeekaboo(
isResolved = true;
// Kill the process
process.kill('SIGTERM');
try {
process.kill('SIGTERM');
} catch (err) {
// Process might already be dead
}
// Give it a moment to terminate gracefully, then force kill
setTimeout(() => {
if (!process.killed) {
try {
// Check if process is still running by trying to send signal 0
process.kill(0);
// If we get here, process is still alive, so force kill it
process.kill('SIGKILL');
} catch (err) {
// Process is already dead, which is what we want
}
}, 1000);