feat(core): support cooperative SIGINT cancellation#1189
Conversation
|
Thanks for the contribution! This is an area I've long wanted to improve and appreciate you digging in. I'll need more time to look through this than your other 2 PRs. One of the main things I'll be looking at is how the design will work for alternate (embedding) hosts of brush-core. As you've noted, our preexisting signal handling is inconsistent and wasn't too thoughtful about ownership of process signal configuration/management in an embedded host -- I'm hoping this will help a bit, given your description. |
|
I have some additional improvements for signal handling that I plan on submitting later that help a lot with both embedding (at least in our environment) and conformance to bash behavior, but I need to time to rework them to make them upstream friendly. Hopefully this one is pretty straightforward as it works for interactive login shells (brush interactive) and embedded cases when you need to emulated it (convert an API call to signal). Let me know if you have any questions. |
dbdd57a to
262b342
Compare
Public API changes for crate: brush-coreAdded itemsPerformance Benchmark Report
Code Coverage Report: Only Changed Files listed
Minimum allowed coverage is Test Summary: bash-completion test suite
|
Add host-requested signal state to execution parameters and checkpoint shell-native execution so loops, lists, and traps can respond without manually instrumenting every AST node. Co-authored-by: Evan Rittenhouse <evan.rittenhouse@magic.dev> Co-authored-by: Milosz Tanski <milosz@magic.dev> Assisted-by: AI
Reset job-control signal dispositions for pipeline children that join an existing process group, and cover host signal delivery across a foreground pipeline. Assisted-by: AI
Forward interactive Ctrl-C into the active shell execution parameters so pure shell loops and INT traps behave like Bash in the built-in interactive shell. Assisted-by: AI
These cases now pass after cooperative SIGINT cancellation and foreground pipeline signal handling were added. Assisted-by: AI
262b342 to
d5272b9
Compare
|
@reubeno I ported the signaling changes from our private branch into this PR. As you can see this fixes a bunch bash signalizing/TRAP compatibility. This also should not hurt embedding (based on our 8mo experience), and exposes the cancel API in such a way it helps embedding cases cancel pipelines in a flexible way. I see I have caused a windows build break, I will TAL when I have some time again. |
Brush currently handles Ctrl-C differently depending on what is running. Bash sends SIGINT to the foreground process group for external commands and pipelines, and it also interrupts shell-native evaluation. If an
INTtrap is installed, Bash runs the trap and lets it decide control flow; otherwise interrupted shell-native work returns the usual SIGINT status.This brings Brush closer to that model for both shell-native execution and foreground processes.
ExecutionParameterscan now carry a host-requested signal, and centralized execution checkpoints let loops, functions, builtins, compound commands, and traps observe cancellation without manually instrumenting every AST node. Foreground process waits can wake on the same signal state and forward the signal to the child process group, including pipelines.The interactive shell wires Ctrl-C into the active execution parameters. In a PTY, the terminal driver already delivers SIGINT to the foreground process group, so the interactive path avoids double-forwarding and uses the cooperative signal path to make Brush's own shell code see the interrupt.
For embedders that drive a shell over an API,
ExecutionParameters::request_host_signal(signal_number)is the hook for injecting a signal into both shell-native execution and foreground children.ExecutionParameters::request_forced_signal(signal_number)is available for timeout/kill-style cancellation that should bypass shell traps.