Interrupting sub-command with Ctrl+C

Hi there!

I'm currently building an application where at some point I spawn a shell command and retrieve its output with Command::new(...).spawn().output().

What I'd like to do is, like Bash or ZSH do, only kill the subcommand when the user presses Ctrl+C.

Currently, it kills the subcommand as well as the Rust program itself, which is not the behaviour I'd like to have.

Ideally this should be cross-platform but at minimum compatible with Linux on *sh shells.

How can I do this?

Thanks in advance for your help!

You would need to intercept the ctrl+c command and manually forward the kill signal to the child. It's probably a bit annoying to do so—I don't think the standard library has any way to catch ctrl+c signals.

1 Like

Ok thanks, it's unfortunate there isn't a native way to do this. I guess I'll go check the ctrlc crate.

Yeah, unfortunately there's a bit of nuance around ctrl-C because of platform-specific quirks and limitations they probably decided to punt on it and let people iterate in the ecosystem first (e.g. you can only communicate with a signal handler via global variables, and you are restricted to async-signal-safe functions - see man 7 signal-safety for more).

I suspect what languages like Python do is register a ctrl-C handler that just sets a global flag and returns, then the main thread periodically checks this flag to see whether it should raise an KeyboardInterrupt.

Rust doesn't benefit from a runtime that can insert these checks automatically, so you either need check the global flag periodically or, like the ctrlc crate, spin up a thread in the background which receives signals and handles them. See nix::sys::signal::signal() for an example.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.