Child::kill
sends a SIGKILL
, but how can I send any other signal such as SIGTERM
? I can probably use libc
and its signal API, but is there a better way to do this?
Asked
Active
Viewed 7,601 times
33

Alen Paul Varghese
- 1,278
- 14
- 27

Oleg Antonyan
- 2,943
- 3
- 28
- 44
-
Does Windows even have the concept of "signal"? If not, there's probably nothing in the standard library. – Shepmaster Mar 10 '18 at 15:37
-
1Oh, windows... :( – Oleg Antonyan Mar 10 '18 at 15:45
-
Windows has [signal](https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx). – jamieguinan Mar 10 '18 at 17:19
-
Does this mean that there is a valid reason to have this functionality in std? – Oleg Antonyan Mar 10 '18 at 18:49
-
Windows only appears to support a very limited subset of the POSIX and SUS signal sets. But at least TERM might be useful to allow a child shut down more gracefully before trying to kill it. But you can just grab the pid and use `libc` instead with some OS-specific code paths. – the8472 Mar 10 '18 at 19:13
-
1On Windows, the closest native equivalent to `SIGTERM` is [`WM_QUERYENDSESSION`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376890(v=vs.85).aspx) + [`WM_ENDSESSION`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376889(v=vs.85).aspx) for GUI applications and [`GenerateConsoleCtrlEvent`](https://learn.microsoft.com/en-us/windows/console/generateconsolectrlevent) for console applications. – Francis Gagné Mar 10 '18 at 20:57
-
3@jamieguinan There is no `kill` though, which is how you actually send a signal. The C run-time library emulates signals by converting some native OS events to signals. An application can only get a `SIGTERM` signal by calling [`raise`](https://msdn.microsoft.com/en-us/library/dwwzkt4c.aspx) to send it to itself. However, `SIGINT` and `SIGBREAK` can be generated from console control events. – Francis Gagné Mar 10 '18 at 21:07
2 Answers
31
The nix
library does a good job of providing idiomatic rust wrappers around low-level UNIX operations, including sending and handling signals. In this case, you would create a nix::Pid
from child_process.id()
, then pass it to kill
like so:
use nix::unistd::Pid;
use nix::sys::signal::{self, Signal};
// Spawn child process.
let mut child = std::process::Command::new();
/* build rest of command */
child.spawn().unwrap();
// Send SIGTERM to child process.
signal::kill(Pid::from_raw(child.id()), Signal::SIGTERM).unwrap();

ecstaticm0rse
- 1,436
- 9
- 17
-
19For those looking to do with just libc: `pub fn kill_gracefully(child: &Child) { unsafe { libc::kill(child.id() as i32, libc::SIGTERM); } }` – Alistair Sep 30 '19 at 02:10
7
Use kill
The kill
command has a bunch of options to send different signals to a process.
You can get the child
's process id using .id()
.
It would be something like
let kill = Command::new("kill")
// TODO: replace `TERM` to signal you want.
.args(["-s", "TERM", &child.id().to_string()])
.spawn()?;
kill.wait()?;
-
I really like this simple solution. Comparing it to the other upvoted answer and given [kill](https://www.unix.com/man-page/posix/1posix/kill/) is POSIX compliant I see no need to bring entire crate in for executing such a simple task. – Peeech Jan 09 '23 at 13:26