Curses, ncurses, threads and non-blocking getch

Hello all.

It looks like non-blocking getch (i.e. when nodelay = 1) with Ruby's
standard curses library blocks when there are other Threads running.
Once the other Thread dies, it resumes non-blocking operation once a key
is pressed. With the ncurses library, this problem doesn't happen.

I'm not a curses/ncurses expert, so maybe I'm doing something wrong.
Here's the code:

  require "curses"

  begin
    Curses.init_screen
    Curses.noecho
    Curses.stdscr.nodelay = 1

    start = Time.now
    Thread.new { sleep 5; }

    while true
      Curses.stdscr.setpos(5, 5)
      Curses.stdscr.addstr("#{(Time.now - start).round} waiting for input...")
      Curses.refresh

      x = Curses.stdscr.getch

      Curses.stdscr.setpos(5, 5)
      Curses.stdscr.addstr("#{(Time.now - start).round} got: #{x} ")
      Curses.refresh

      sleep 0.5
    end
  ensure
    Curses.echo
    Curses.close_screen
  end

You'll see that getch blocks ("waiting for input" is displayed) until
after the first five seconds, when the thread dies. Then as soon as you
press a key, getch is back in non-blocking mode. If you remove the
Thread.new call, everything works as it should.

This is on ruby 1.8.2 (2005-01-10) [i386-linux].

For reference, here's the equivalent Ncurses code, which works fine:

  require "ncurses"

  begin
    Ncurses.initscr
    Ncurses.noecho
    Ncurses.stdscr.nodelay true

    start = Time.now
    Thread.new { sleep 5; }

    while true
      Ncurses.stdscr.move(5, 5)
      Ncurses.stdscr.addstr("#{(Time.now - start).round} waiting for input...")
      Ncurses.refresh

      x = Ncurses.stdscr.getch

      Ncurses.stdscr.move(5, 5)
      Ncurses.stdscr.addstr("#{(Time.now - start).round} got: #{x} ")
      Ncurses.refresh

      sleep 0.5
    end
  ensure
    Ncurses.endwin
  end

···

--
William <wmorgan-ruby-talk@masanjin.net>