Kill child process while waiting for it

前端 未结 2 641
南方客
南方客 2020-12-11 07:51

I want to execute another process and normally want to wait until it has finished. Lets say we spawn and wait for the process in thread T1:

let child = Comma         


        
相关标签:
2条回答
  • 2020-12-11 08:14

    Obviously, you can just kill the process yourself. The Child::id method gives you the "OS-assigned process identifier" that should be sufficient for that.

    The only problem is that killing a process is a platform-dependent action. On UNIX killing a process is handled with the kill function:

    #![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();
    }
    

    On Windows you might try the OpenProcess and TerminateProcess functions (available with the kernel32-sys crate).

    0 讨论(0)
  • 2020-12-11 08:19

    If the child subprocess do not close stdout before finishing, it's possible to wait reading stdout. Here is an example

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

    The output of this program on my system is

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

    Although not in the docs, killing a finished child returns Ok.

    This works because killing a process close the files associated with it. However, if the child spawn new processes, killing the child may not kill these other processes and they may keep the stdout opened.

    0 讨论(0)
提交回复
热议问题