I am trying to write a program in Rust that writes a string to a named pipe. However, the data only shows up on the receiving end after the program quits.
Here's my code:
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::Write;
use std::fs::{File, OpenOptions};
fn send_data(file: &mut File, payload: &str) -> Result<(), std::io::Error> {
file.write(payload.as_bytes()).unwrap();
// I tried file.write_all() and file.flush(); same result
Ok(())
}
fn main() {
let mut file = OpenOptions::new()
.write(true)
.open("/tmp/my_named_pipe")
.expect("Failed to open named pipe for writing");
let mut stdout = std::io::stdout().into_raw_mode().unwrap();
stdout.flush().unwrap();
loop {
let key = match std::io::stdin().keys().next() {
Some(Ok(input)) => input,
_ => break,
};
match key { // press x to send data, q to quit
Key::Char('q') => break,
Key::Char('x') => send_data(&mut file, "foobar").unwrap(),
_ => (),
}
}
}
I'm creating a named pipe with mkfifo /tmp/my_named_pipe
and start listening to it with tail -f /tmp/my_named_pipe
. Then, in a different terminal window, I run my program (and press 'x' several times). The 'tail -f' doesn't show anything. When I quit my program (by pressing 'q') all strings show all at once.
I'd expect every key press to call send_data()
and every call to render on the tail -f
side immediately. How can this be accomplished?
tail -f
does not print incomplete lines. You can see the same behavior if you replace your program with{ printf x; sleep 1; echo; }
You need something that reads the fifo without waiting for complete lines.echo "foobar" > /tmp/my_named_pipe
in a different terminal does exactly what I want my rust program to do.tail
needs\n
(see earlier comment). So include in program. Then test, then post new tested program in question.tail -f
not properly watching the pipe.cat /tmp/my_named_pipe
works perfectly even without\n
.tail -f
is misbehaving...)