I've been recently encountered a major problem with a program i am
coding.
Main in my program outputs a menu with some cases you can choose,
1,2,3.. so i have a gets at the end of the menu. However, my program
also checks for timestamps with a seperate thread (thread 2). And it
appeared that the thread bugged when I used gets, since i have 3 if
conditions in my thread 2, and if i for example replace gets with
sleep(200), the if conditions runs as it should. But when I have the
gets, it never runs. Later I found out that there is appearently a bug
in Ruby with standard I/O and threads in Windows?
It's more like a bug (or "misfeature") of Windows, in that select() is broken for file handles and pipes. Prior to ruby 1.9, ruby uses select() internally to wait for I/O while performing its own thread
scheduling.
So, how can i workaround this bug? Is there any alternative method for
input or so?
Ruby 1.9 will work, since 1.9 now uses OS native threads. So gets()
will block its thread, without blocking the whole process.
If you need to use 1.8, it is possible to write a nonblocking gets on
windows using kbhit/getch:
···
From: "Hello There" <abbb812@gmail.com>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require 'Win32API'
class Win32GetsNonblock
@@kbhit_proc = Win32API.new("msvcrt", "_kbhit", , 'I')
@@getch_proc = Win32API.new("msvcrt", "_getch", , 'I')
class << self
def gets
str = ""
begin
ch = getch
ch = ?\n if ch == ?\r
str << ch.chr
end until ch == ?\n
str
end
def kbhit
@@kbhit_proc.call != 0
end
def getch
sleep 0.1 until kbhit
@@getch_proc.call
end
end
end
# example.......
th = Thread.new { loop {puts Time.now; sleep 1} }
x = Win32GetsNonblock.gets
p x
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note, I have only tried the above on
ruby 1.8.4 (2005-12-24) [i386-mswin32]
Hope this helps,
Bill