我如何向“子”子进程发送信号?

34

Child::kill 发送一个 SIGKILL 信号,但我如何发送其他信号,例如 SIGTERM?我可能可以使用 libc 和其信号 API,但是否有更好的方法来实现这一点?


1
哦,Windows... :( - Oleg Antonyan
Windows有信号 - jamieguinan
Windows似乎只支持POSIX和SUS信号集的非常有限的子集。但至少TERM可能会很有用,允许子进程在尝试杀死它之前更优雅地关闭。但是你可以获取pid并使用libc,配合一些特定于操作系统的代码路径。 - the8472
1
在Windows上,与SIGTERM最接近的本地等效方式是WM_QUERYENDSESSION + WM_ENDSESSION,适用于GUI应用程序,而对于控制台应用程序,则使用GenerateConsoleCtrlEvent - Francis Gagné
3
@jamieguinan 中并没有kill命令,而这正是发送信号的方式。C运行时库通过将某些本机操作系统事件转换为信号来模拟信号。应用程序只能通过调用raise向自身发送SIGTERM信号。然而,SIGINTSIGBREAK可以从控制台控制事件中生成。 - Francis Gagné
显示剩余2条评论
2个回答

34

nix库在提供UNIX底层操作的习惯用法的同时,也很好地处理了发送和处理信号的操作。在这种情况下,您可以从child_process.id()创建一个nix::Pid,然后将其传递给kill函数:

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();

19
对于那些只想使用libc的人:pub fn kill_gracefully(child: &Child) { unsafe { libc::kill(child.id() as i32, libc::SIGTERM); } }该函数使用libc,以优雅的方式杀死一个子进程。 - Alistair

7

使用kill

kill命令有许多选项,可以向进程发送不同的信号。 您可以使用.id()获取child进程的进程ID。

它可能是这样的:

let kill = Command::new("kill")
    // TODO: replace `TERM` to signal you want.
    .args(["-s", "TERM", &child.id().to_string()])
    .spawn()?;
kill.wait()?;

我真的很喜欢这个简单的解决方案。与其他得到赞同的答案进行比较,并且考虑到 kill 是符合 POSIX 标准的,我认为没有必要为执行如此简单的任务而引入整个 crate。 - Peeech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接