Relationships
#1156 Blocked model methods are uninterruptible: SIGINT/SIGTERM don't force-exit; no cancellation signal for execute()
Opened by kneel · 7/14/2026· Shipped 7/16/2026
Summary
When a model method blocks (e.g. on a subprocess), swamp catches SIGINT/SIGTERM
but never force-exits — repeated Ctrl-C has no effect and the run can only be
ended with SIGKILL. There is also no cancellation signal exposed to a model's
execute, so extensions have no way to abort in-flight work on interrupt.
Environment
- swamp
20260711.232311.0-sha.6bda08e7(Linux x86-64)
Evidence
The swamp process registers custom handlers for SIGINT/SIGTERM/SIGHUP:
/proc/<pid>/status
SigCgt: 0000000100004443 # HUP + INT + TERM caught (custom handlers)…but delivering those signals directly to the process does nothing — it stays
in S (sleeping), frozen mid-method, holding the datastore .lock:
kill -INT <pid> # x3, ignored
kill -TERM <pid> # ignored
kill -HUP <pid> # ignored
kill -KILL <pid> # only this ends itThe handler waits indefinitely for the in-flight method promise to settle. If
the method is blocked in an uncancellable call (e.g. await [HOST-1]()
with no signal:), that promise never settles and the process is wedged.
Requested behavior (defense-in-depth)
- Expose a per-run cancellation
AbortSignalto modelexecute(args, context)so extensions can wire it intoDeno.Command({ signal })and other awaits. - On SIGINT: fire that signal (graceful cancel). On a second SIGINT (or after a short grace period), force-exit the process — releasing/soft-breaking the datastore lock — rather than waiting forever for the method.
Related
Downstream extension-side instance of this (ssh child never aborted): Lab #1155.
Shipped
Click a lifecycle step above to view its details.