Mikołaj
Mikołaj

Reputation: 13

Interrupt std::io::read() in Rust

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?

Upvotes: 1

Views: 617

Answers (1)

Jmb
Jmb

Reputation: 23264

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

Upvotes: 1

Related Questions