1

I have been trying to write an application that invokes a system command in a separate thread.

The key characteristic is that I want to be able to kill this command and invoke a new one from the main thread upon request.

My secondary thread looks like so:

let (tx, rx): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel();

let child_handle = stoppable_thread::spawn(move |stop| {
  let mut child = Command::new("[the program]").arg(format!("-g {}", gain)).stdout(Stdio::piped()).spawn().expect("naw man");
  let mut childout = child.stdout.as_mut().unwrap();
  while !stop.get() {
    let mut buffer = [0; 128];
    childout.try_read(&mut buffer).unwrap(); // This part makes the code wait for the next output
    // Here the buffer is sent via mpsc irrelevant to the issue
}});

The problem is when I send a stop signal (or if I used an mpsc channel to notify the thread to stop) it waits for the command to output something to stdout. This is unwanted behavior.

How can I remedy this? How can I interrupt the read() function?

Mikołaj
  • 13
  • 2
  • Does this answer your question? [How to terminate or suspend a Rust thread from another thread?](https://stackoverflow.com/questions/26199926/how-to-terminate-or-suspend-a-rust-thread-from-another-thread) – Ibraheem Ahmed Jan 07 '21 at 19:28
  • It does not, This is used in the code snippet, my question is about interrupting the read() command. – Mikołaj Jan 07 '21 at 21:47

1 Answers1

1

You can kill the child process, which will cause it to close its output, at which point read will see an EOF and return. However, this requires sending the child to the parent thread. Something like:

let (tx, rx): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel();
let (ctx, crx) = mpsc::channel();

let child_handle = stoppable_thread::spawn(move |stop| {
  let mut child = Command::new("[the program]").arg(format!("-g {}", gain)).stdout(Stdio::piped()).spawn().expect("naw man");
  let mut childout = child.stdout.take().unwrap();
  ctx.send (child);
  while !stop.get() {
    let mut buffer = [0; 128];
    childout.try_read(&mut buffer).unwrap(); // This part makes the code wait for the next output
    // Here the buffer is sent via mpsc irrelevant to the issue
}});

// When you want to stop:
let child = crx.recv().unwrap();
child.kill().unwrap();
Jmb
  • 18,893
  • 2
  • 28
  • 55