console-rs/console

read_char() breaks println! in other threads

bugeats opened this issue · 5 comments

use console::Term;

fn main() {
    let thread1 = std::thread::spawn(|| loop {
        println!("line");
        std::thread::sleep(std::time::Duration::from_millis(250));
    });

    let stdout = Term::buffered_stdout();
    stdout.read_char().unwrap();

    thread1.join().unwrap();
}

OUTPUT:

line
    line
        line
            line

EXPECTED:

line
line
line
line

I don't know if I'm doing something wrong, but listening for chars on one thread is breaking (carriage returns?) output on other threads.

I believe that this cannot be fixed because read_char moves the terminal into raw mode.

I have the same issue.
Is there any workaround?

Indeed the terminal is set to raw mode in read_single_key(). But this may be overkill regarding what the function actually requires. In particular cfmakeraw() also disables all output processing from the terminal.

This single line fixes the behavior reported here:

    unsafe { libc::cfmakeraw(&mut termios) };
    termios.c_oflag = original.c_oflag;

As it only changes the output attributes, I think it won't interfere with the rest of the function, but I did not test it extensively. Also it may be more elegant to actually determine the precise termios flag set required, but I'm not knowledgeable enough on terminal control attributes to really figure that out.

I have the same issue. Is there any workaround?

Sort of, I have had success by inserting a carriage return before every single printed newline. So basically instead of /n use /r/n.

I have the same issue.
Is there any workaround?

I wrote a console wrapper to solve all the raw mode issues:
https://github.com/JasonWei512/code-radio-cli/blob/cc68773b3123fb580c21dbf92ff1a1565607a7a6/src/terminal.rs