How mimic ^C programatically for Command::new(&cmd[0])...spawn()?

I can terminate Rust program from a terminal pressing ^C. However when I run the same program using Rust command, I do not know how to do that. It's possible to look in source of Rust terminal, however to save some time, maybe someone already implemented that and can help me?

When I was writing the question, I thought, maybe I need just send 03 to stdin? Let me check.

What platform?

Assuming you're on a unixy platform..

The way to "Ctrl+C" terminate a process is by sending the SIGINT signal to it.

I think this is the basic way to do it:

  1. Find out the pid of the spawned process.
  2. Use libc/nix crate to call the kill() syscall, passing in the pid and SIGINT.

Edit: kill(), pid

Thanks, it sounds reasonable. I thought also something about that using the kill. But certainly, your solution is more elegant. When I programmed using Java, I always ended by one solution working on all platforms and also I had only one computer. Now, I need to own 3 computers and issue a solution for every platform. So, hopefully somebody with Windows background will help me too.

I haven't actually done this on Windows, but I thought I was going to need to a few years ago so I started read up on it back then. Basically you generate something called "console control events", which is not completely unlike signals. However, I recall being confused about how to acquire the required process group handle. It's probably not difficult (at least not once you find some nice example written in C..).

Anywho, you can read about it here.

Actually, after reading Rust API, I found that kill() does what I need. Thanks again, you showed how to dig in the right direction.

1 Like

Child::kill doesn't quite do the same thing as Ctrl-C, though it's close. Assuming you're targeting unix-like systems (Linux, MacOS, any BSD, etc):

  • Ctrl-C, in most terminals, delivers SIGINT to the process leading the process group. The default handling of SIGINT is to exit immediately, but a process can set up a signal handler for SIGINT, and do something else. It's fairly common for programs that handle long-running tasks to implement some kind of clean shutdown for SIGINT, for example.
  • kill() sends SIGKILL to the target process. The only handling of SIGKILL is to exit immediately. Processes (other than PID 1) cannot intercept SIGKILL with a signal handler, or ignore it. It will always cause your program to exit as if it has crashed on the spot.

The difference may or may not matter for your needs, but you should know that there is a difference, and that it can affect some programs you might run this way. I hope this helps you write better software!

2 Likes

I'm pretty sure it sends SIGINT to all processes in the foreground process group, not just the initial process.

Thanks guys, it's a nice information. Although currently I target mostly killing applications, applying SIGINT to my application itself makes me thinking about the standard BASH behavior. I will clear screen and reappear the prompt.