From: Robert Klemme Date: 2008-08-07T17:04:31+09:00 Subject: Re: Threaded IO trouble 2008/8/6 Michal Suchanek : > On 06/08/2008, Michal Suchanek wrote: >> Hello >> >> I do not understand the internals of Ruby IO but what I get here looks >> really awful. >> >> I am interfacing an application that processes lines of text and >> buffers part of the output until EOF (or EOF tag). I thought using an >> additional thread would be the right thing to do in this case: one >> thread writes stuff, and as the application starts to output stuff >> another thread wakes up to read it. >> >> There are two problems here: >> >> 1) only reading inside the separate thread is possible, writing causes >> stdin to be read into the program >> >> 2) reading inside the thread produces deadlocks >> >> Attaching the files required to reproduce both failures. >> >> =================== mock.rb =================== >> buf=[] >> while l=gets >> buf << l >> puts buf.shift if buf.length >3 >> end > Actually the mockup misses a line here: > > while l = buf.shift do puts l end And it misses another line at the beginning: $defout.sync = true :-) With that change for me this works as expected: 10:04:42 Temp$ ./ttest.rb 1218096292.04: main : 0 1218096293.07: main : 1 1218096297.08: main : 2 1218096298.08: main : 3 1218096298.08: reader : 0 1218096303.08: main : 4 1218096303.08: reader : 1 1218096306.09: reader : 2 1218096306.09: reader : 3 1218096306.09: reader : 4 10:05:06 Temp$ cat ttest.rb #!/bin/env ruby def log(m) t = Thread.current printf "%10.2f: %-10s: %s\n", Time.now, t[:label] || t.inspect, m end Thread.current[:label] = "main" IO.popen "./mock.rb", "r+" do |io| io.sync = true t = Thread.new do Thread.current[:label] = "reader" io.each do |line| log line.chomp end end 5.times do |i| log i io.puts i sleep(1 + rand(5)) end io.close_write t.join end 10:05:08 Temp$ Kind regards robert -- use.inject do |as, often| as.you_can - without end