在等待它时杀死孩子的过程

时间:2016-01-29 20:53:49

标签: rust

我想执行另一个进程,通常要等到它完成。假设我们在线程T1中生成并等待进程:

let child = Command::new("rustc").spawn().unwrap();
child.wait();

现在,如果发生特殊事件(T0正在等待哪个线程),我想杀死衍生过程:

if let Ok(event) = special_event_notifier.recv() {
    child.kill();
}

但是我没有办法做到这一点:killwait都引用Child的可变引用,因此是互斥的。致电wait后,任何人都无法再引用child

我找到了wait-timeout箱子,但我想知道是否还有其他办法。

2 个答案:

答案 0 :(得分:2)

显然,你可以自己杀死这个过程。 Child::id方法为您提供" OS分配的进程标识符"这应该足够了。

唯一的问题是杀死进程是依赖于平台的操作。在UNIX上,使用OpenProcess函数处理进程:

#![feature(libc)]
extern crate libc;
use std::env::args;
use std::process::Command;
use std::thread::{spawn, sleep};
use std::time::Duration;
use libc::{kill, SIGTERM};

fn main() {
    let mut child = Command::new("/bin/sh").arg("-c").arg("sleep 1; echo foo").spawn().unwrap();
    let child_id = child.id();
    if args().any(|arg| arg == "--kill") {
        spawn(move || {
            sleep(Duration::from_millis(100));
            unsafe {
                kill(child_id as i32, SIGTERM);
            }
        });
    }
    child.wait().unwrap();
}

在Windows上,您可以尝试使用TerminateProcesskernel32-sys功能(可在http://kamsar.net/index.php/2015/02/sitecore-8-experience-editor-performance-optimization/包中使用)。

答案 1 :(得分:2)

如果子子进程在完成之前没有关闭stdout,则可以等待读取stdout。这是一个例子

use std::io::Read;
use std::process::*;
use std::thread;
use std::time::Duration;

fn wait_on_output(mut out: ChildStdout) {
    while out.read_exact(&mut [0; 1024]).is_ok() { }
}

fn wait_or_kill(cmd: &mut Command, max: Duration) {
    let mut child = cmd.stdout(Stdio::piped())
                       .spawn()
                       .expect("Cannot spawn child");

    let out = child.stdout.take().expect("No stdout on child");

    let h = thread::spawn(move || {
        thread::sleep(max);
        child.kill().expect("Cannot kill child");
        println!("{:?}", child.wait());
    });

    wait_on_output(out);
    h.join().expect("join fail");
}

fn main() {
    wait_or_kill(Command::new("sleep").arg("1"), Duration::new(2, 0));
    wait_or_kill(Command::new("sleep").arg("3"), Duration::new(2, 0));
}

我的系统上该程序的输出是

Ok(ExitStatus(ExitStatus(0)))
Ok(ExitStatus(ExitStatus(9)))

虽然不在文档中,但杀死已完成的孩子会返回Ok

这是有效的,因为终止进程会关闭与之关联的文件。但是,如果孩子产生新的进程,杀死孩子可能不会杀死这些其他进程,并且他们可能会保持stdout打开。