如果我的应用程序发生混乱,如何确保生成的Child进程被终止?

时间:2015-05-29 19:52:21

标签: rust child-process zombie-process

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

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

// do some tests

server.kill();

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

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

2 个答案:

答案 0 :(得分:4)

您可以将可能恐慌的代码放入闭包中,并将该闭包赋予catch_paniccatch_panic的行为与scopedspawn ed线程对join的行为方式相同。如果关闭恐慌,它会返回带有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

答案 1 :(得分:3)

如果离开给定范围,可以使用标准RAII模式来确保子线程被杀死。如果你想在恐慌时杀死你的孩子,你可以在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");
}