* Kill a process
(processId: string)
| 513 | * Kill a process |
| 514 | */ |
| 515 | async function handleKill(processId: string): Promise<KillResponse> { |
| 516 | logger.info("[Process:kill] Killing process", JSON.stringify({ processId })) |
| 517 | |
| 518 | const proc = activeProcesses.get(processId) |
| 519 | if (!proc) { |
| 520 | return { ok: false, error: "Process not found" } |
| 521 | } |
| 522 | |
| 523 | try { |
| 524 | if (!proc.completed && proc.process && proc.process.pid) { |
| 525 | // Kill the entire process group (negative PID) since we spawn with detached: true |
| 526 | try { |
| 527 | process.kill(-proc.process.pid, "SIGTERM") |
| 528 | } catch (err) { |
| 529 | // Fallback to killing just the process if group kill fails |
| 530 | logger.debug('[Process] Error killing process group, falling back to direct kill:', err) |
| 531 | proc.process.kill("SIGTERM") |
| 532 | } |
| 533 | // Force kill after 5 seconds |
| 534 | setTimeout(() => { |
| 535 | if (!proc.process.killed && proc.process.pid) { |
| 536 | try { |
| 537 | process.kill(-proc.process.pid, "SIGKILL") |
| 538 | } catch (err) { |
| 539 | logger.debug('[Process] Error force killing process group, falling back to direct kill:', err) |
| 540 | proc.process.kill("SIGKILL") |
| 541 | } |
| 542 | } |
| 543 | }, 5000) |
| 544 | } |
| 545 | |
| 546 | // Clean up immediately |
| 547 | if (proc.cleanupTimeoutId) { |
| 548 | clearTimeout(proc.cleanupTimeoutId) |
| 549 | } |
| 550 | if (proc.tempScriptPath && fs.existsSync(proc.tempScriptPath)) { |
| 551 | try { |
| 552 | fs.unlinkSync(proc.tempScriptPath) |
| 553 | } catch (err) { |
| 554 | logger.debug('[Process] Error cleaning up temp script on kill:', err) |
| 555 | } |
| 556 | } |
| 557 | activeProcesses.delete(processId) |
| 558 | |
| 559 | return { ok: true } |
| 560 | } catch (error: unknown) { |
| 561 | const errorMessage = error instanceof Error ? error.message : "Unknown error" |
| 562 | return { ok: false, error: errorMessage } |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | /** |
| 567 | * List active processes |
no test coverage detected