`Command` timeouts?

Hi all,

I'm running Commands in a threadpool::ThreadPool, and I need to apply a timeout to each command (i.e., I don't want them running longer that x number of minutes).

I've tried using the try_wait function on a Child in a loop, things seem to get hung up and never finish.

Any suggestions?

Thanks!

Can you post your loop?

Unfortunately I trashed it, but it went something like this:

let exe_path = // ... a PathBuf ..
let mut command = Command::new(&exe_path);
// ... set up the command's arguments and working directory
let mut child = command.spawn().unwrap();
loop {
    match child.try_wait() {
        Ok(Some(status)) => {
            // gather the stdout and stderr into an Output struct
            break;
        }
        Ok(None) => {
            // if it's been too long since we spawned the child process kill it and break
        }
        Err(e) => {
            child.kill().expect("unable to kill process");
            break;
        }
    }
}

I mean it looks reasonable to me.

Note that you should probably call yield_now or similar in the loop to sleep a little bit, although I don't think that's the problem.

Oh, good call on yield_now.

I also tried to put child.wait() at the beginning of the Ok(Some(status)) but that didn't help either (the documentation mentions that it's necessary on some systems for releasing resources)...

Here's the rough idea of the solution I ended up with:

enum Msg {
   Start(u32),
   End(std::io::Result<std::process::Output>),
}
let (tx, rx) = crossbeam::channel::unbounded();
let proc = std::thread::spawn(move || {
    // I'll show this to the user in case something bad
    // happens and they need to kill the process manually
    let _ = tx.send(Msg::Start(std::process::id());
    // create and run command
    // wait on the output
    let _ = tx.send(Msg::End(Ok(output)));
});
let mut pid: u32 = 0;
loop {
    match rx.try_recv() {
        Ok(Msg::Start(id)) => { pid = id; }
        Ok(Msg::End(output)) => {
            // handle output
        }
        Err(e) => {
            match e {
                crossbeam::TryRecvError::Empty => {
                    // check if we've spent too much time waiting and exit if so
                }
                _ => {
                    // the channel got disconnected - exit
                }
            }
        }
    }
}