Is it possible to interrupt/cancel io::stdin().read_line()
or interrupt stdin read before returning on a newline?
I have one thread polling for signals, which when received SIGINT
should stop io::stdin().read_line()
.
use std::io::Write;
use std::{io, thread};
use std::error::Error;
use std::sync::{Arc, atomic::AtomicUsize, atomic::Ordering};
use signal_hook::consts::signal;
use signal_hook::flag;
const SIGINT_U: usize = signal::SIGINT as usize;
fn main() -> Result<(), Box<dyn Error>> {
let term = Arc::new(AtomicUsize::new(0));
signal_hook::flag::register_usize(signal::SIGINT, Arc::clone(&term), SIGINT_U).unwrap();
thread::spawn(move || loop {
match term.load(Ordering::Relaxed) {
0 => {
// do nothing
},
SIGINT_U => {
// interrupt running read_line()
},
_ => unreachable!()
}
});
loop {
print!("> ");
io::stdout().flush().unwrap();
let mut line = String::new();
io::stdin()
.read_line(&mut line)
.expect("Failed to read stdin");
let command = line.trim_end().trim_start().to_lowercase();
if command == "exit" {
break;
}
println!("received: {}", line);
}
}
The effect should be the same if we instead put io::stdin().read_line()
into a separate thread and the SIGINT
check inside the main loop.
The problem is, when read_line()
is reached, stdin won't stop being read until a newline character is reached. This is the standard and expected behavior, but I'd hope I could somehow stop its execution. Albeit through stopping killing a thread running it, or somehow cancelling its return and stop without reading stdin.
I did try to put read_line()
on a separate thread and detect when SIGINT
was received. But it wouldn't matter, because the thread loop can't be stopped while read_line()
executes, only before or after it.
I thought that maybe I could kill the thread running read_line()
, but apparently it's not possible to kill threads.