Problems calling `read_char` in separate fiber

OS: Ubuntu 20.04
Crystal version: 0.35.1

Minimum code example:

ch = Channel(Nil).new

spawn do
  loop do
    str = STDIN.raw &.read_char
    ch.send(nil) if str == 'q'  
  end    
end

ch.receive

How to run:

# execute it in terminal
crystal run ./example.cr

This code spawns new fiber and awaits until user enters a character in the loop. As soon as q is entered loop the program stops.

However, after program is terminated when you enter anything in terminal the characters are not displayed. Terminal window becomes unusable and bust be restarted.

I think I misuse read_char somehow, like after channel unblocked main fiber execution I need to stop reading from STDIN or smth. Will much appreciate an advice how to fix it.

Adding a simple sleep 1 after ch.receive could be a quick fix for this. I’m not sure, though. The filedescriptor should’ve been reset before the message is sent to the channel (and thus before the program terminates). Delaying program exit might help.

However, I would recommend to use a library for proper TTY handling. IO#raw is a not a good tool for that.
There are multiple bindings available for ncurses for example: https://shardbox.org/search?q=ncurses
I haven’t tried any of them, so no recommendation.

Nope, that didn’t help. Will try out some libraries.

Have your tried to reset the terminal at program exit via:
STDIN.cooked!
API: