Relationships
↔ sibling #2915#2910 model cancel SIGKILLs the owner 2 s after SIGTERM, before the step executor's own 3 s kill grace, so the run never records its own cancellation
Opened by hammz · 10/1/2026· Shipped 10/1/2026
Description
swamp model cancel (src/cli/commands/model_cancel.ts) stops the owning process with killProcessTree and the default maxWaitMs of 2000. The shell step executor waits KILL_GRACE_MS (3 s, src/infrastructure/process/process_executor.ts) between SIGTERM and SIGKILL for a step that ignores SIGTERM, and then drains its pipes for up to 5 s, before the owner saves the method run's cancelled output. Any method whose process takes more than about 2 s to stop is therefore SIGKILLed together with its owner. Its own cancellation (data, output status, logs) is never written; only the tracker row is completed as cancelled by the cancel command.
This is the sibling of swamp-club#2897, which fixed the same 2 s window for workflow cancel by waiting OWNER_STOP_GRACE_MS and re-snapshotting children before SIGKILL. model cancel was left on the 2 s default because it has no cleanup phase. The kill grace mismatch still applies.
A second, smaller problem: model cancel --all calls killProcessTree once per tracker row. When several running method runs share one owner pid, the owner gets a second SIGTERM, and owners registered with forceExitOnRepeat exit at once instead of shutting down cleanly. workflow cancel --all now dedupes owner pids (swamp-club#2897).
Found by code reading while fixing swamp-club#2897. Not yet reproduced end to end; the workflow cancel equivalent was reproduced, with exit 137 and the step recorded wrongly.
Steps to reproduce (suggested)
- Create a command/shell model whose method traps TERM and keeps running for about 5 s, for example: trap 'sleep 5' TERM; sleep 60
- swamp model method run execute in one shell.
- From a second shell: swamp model cancel
Actual (expected from the code, not yet observed)
The owner is SIGKILLed about 2 s after the cancel (exit 137). The method run's output never records the cancellation.
Expected
model cancel gives the owner at least the step executor's kill grace plus drain time (or a shared constant derived from them) before escalating. The owner records its own cancellation. --all signals each owner pid once.
Shipped
Click a lifecycle step above to view its details.