More investigations:

If I change getc.to_s to sysread(1) in posted source, it works ok.

I have investigated what is going on using strace and gdb:
Problem is AFAIK in combination of select+threads+buffered stream.
(I have changed thread to do sleep 1000 to avoid big strace logs)

My strace log: (my comments are orefixed with ####)

write(1, "select: [[#<IO:0x401e9090>, #<Fi"..., 64select: [[#<IO:0x401e9090>, #<File:0x401e2394>], nil, nil, nil]
) = 64
gettimeofday({1006622392, 833171}, NULL) = 0

#### ruby select will wait:

select(5, [0 3], [], [], {999, 998085}a

#### I have entered 'a' and enter

) = 1 (in [0], left {988, 110000})
write(1, "select returned: [[#<IO:0x401e90"..., 46select returned: [[#<IO:0x401e9090>], [], []]
) = 46

#### return is correct: f1

write(1, "f1 will read\n", 13f1 will read
)          = 13
gettimeofday({1006622404, 730466}, NULL) = 0
select(1, [0], [], [], {988, 100790})   = 1 (in [0], left {988, 110000})
fstat64(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40027000
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0

#### now actual read (getc version)

read(0, "a\n", 1024)                    = 2

#### two characters were read, other one is buffered

write(1, "f1: 97\n", 7f1: 97
)                 = 7
--- SIGVTALRM (Virtual timer expired) ---
sigreturn()                             = ? (mask now [])
gettimeofday({1006622404, 733123}, NULL) = 0
select(0, [], [], [], {0, 0})           = 0 (Timeout)

#### What is this above? The select call above is useless!

#### internal ruby select returned due to buffered character, but returned both f1 and f2!:

write(1, "select: [[#<IO:0x401e9090>, #<Fi"..., 64select: [[#<IO:0x401e9090>, #<File:0x401e2394>], nil, nil, nil]
) = 64
gettimeofday({1006622404, 733855}, NULL) = 0
gettimeofday({1006622404, 733965}, NULL) = 0
gettimeofday({1006622404, 734061}, NULL) = 0
select(5, [0 3], [], [], {0, 0})        = 0 (Timeout)
write(1, "select returned: [[#<IO:0x401e90"..., 66select returned: [[#<IO:0x401e9090>, #<File:0x401e2394>], [], []]
) = 66
write(1, "f1 will read\n", 13f1 will read
)          = 13
write(1, "f1: 10\n", 7f1: 10
)                 = 7
write(1, "f2 will read\n", 13f2 will read
)          = 13
gettimeofday({1006622404, 735405}, NULL) = 0
select(4, [3], [], [], {988, 95851}
#### deadlock no data on f2 ready


Jakub Travnik wrote:

> Hello,
> 
> I found a bug in ruby select method.
> Bug is easily repeatable on:
> Linux 2.4.3 with:
> ruby 1.6.5 stable
> ruby stable-snapshot 2001-11-23
> 
> Description:
>  Select call with first paramter filled with IO objects should
> return IO objects that will not block for next read. It does not
> work when there is an another thread. Following code demonstrate
> this:
> --8<---------------
> require 'thread'
> 
> f1=$stdin # choose any devices that you can read interactively
> f2=File.open('/dev/tty8')
> 
> puts "f1: #{f1}"
> puts "f2: #{f2}"
> 
> =begin
> # uncomment this to see bug
> Thread.new{
>   loop{ }
> }
> =end
> 
> loop{
>   puts "select: #{[[f1,f2],nil,nil,nil].inspect}"
>   res=select([f1,f2],nil,nil,nil)
>   puts "select returned: #{res.inspect}"
>   if res
>     res=res[0]
>     if res.include?(f1)
>       puts 'f1 will read'
>       puts 'f1: '+f1.getc.to_s
>     end
>     if res.include?(f2)
>       puts 'f2 will read'
>       puts 'f2: '+f2.getc.to_s
>     end
>   end
> }
> --8<---------------
> 
> I have used free allocated consoles /dev/tty8.
> Make sure you have no X11 running there!
> You can allocate virtual consoles with chvt command.
> However it is not significant for this bug, f1 and f2 can be
> TCPSocket, UNIXSocket too (like in configuration where bug
> appeared first).
> Run this, try that you can type something on f1 and f2
> (on consoles enter is required to flush line).
> 
> You should see, that select is returning one IO object at time
> (as you feed f1 and f2 with text).
> 
> Now, the bug.
> Uncomment thread and run this again. Select returns both f1
> and f2 even when there are no ready data in one of them.
> 
> Thread may be running or blocked in blocking read
> (of another IO object) - it does not matter.
> 
> 
> Jakub Travnik
> jabber://jtra / jabber.com
> ICQ: 6770334 (deprecated)
>