如果我的应用程序崩溃,我如何确保派生的子进程被终止?

How do I ensure that a spawned Child process is killed if my app panics?

我正在编写一个启动守护进程并对其进行测试的小测试,例如:

let server = Command::new("target/debug/server").spawn();

// do some tests

server.kill();

测试失败的典型方式是恐慌。不幸的是,这意味着 kill() 永远不会被调用并且测试套件的重复运行失败,因为端口被仍然是 运行.

的旧进程占用

是否有类似 TRAP 功能的东西可以用来确保 Child 被杀死?

您可以将可能引起恐慌的代码放入一个闭包中,然后将该闭包交给 catch_paniccatch_panic 的行为与 scopedspawned 线程对 joining 的行为相同。它 returns 带有 Ok(ClosureRetVal)Err(Box<Any>) 的结果(如果闭包出现恐慌)。

let res = std::thread::catch_panic(|| {
    panic!("blub: {}", 35);
});
if let Err(err) = res {
    let msg: String = *err.downcast().unwrap();
    println!("{}", msg);
}

PlayPen

您可以使用标准 RAII 模式来确保 child 线程在您离开给定范围时被终止。如果你只想在恐慌时杀死你的child,你可以插入一个检查std::thread::panicking

use std::process::{Command,Child};

struct ChildGuard(Child);

impl Drop for ChildGuard {
    fn drop(&mut self) {
        // You can check std::thread::panicking() here
        match self.0.kill() {
            Err(e) => println!("Could not kill child process: {}", e),
            Ok(_) => println!("Successfully killed child process"),
        }
    }
}

fn main() {
    let child = Command::new("/bin/cat").spawn().unwrap();
    let _guard = ChildGuard(child);

    panic!("Main thread panicking");
}