From: Joel VanderWerf Date: 2010-09-07T06:53:13+09:00 Subject: Re: trouble with mkfifo and forks On 09/06/2010 01:10 PM, Josh wrote: > # In a nutshell: > 1) Create a pipe > 2) Fork twice > 3) Each for sends 10 strings over the pipe > 4) See what comes out the other side I'm probably naive about something, but fifos almost never work right for what I want to do, and I usually end up using (unix domain) sockets (which also makes it easier to move to tcp sockets if you need to distribute across hosts). Anyway, in your code, it seems that the repeated closing of the *read* end of the pipe causes some data to be lost. If you can modify your read loop to keep using the same IO object, it seems to work (see below). Also, I found I needed to watch for #gets returning nil (though that doesn't happen reliably). Perhaps someone who knows more about pipes will "pipe up" on this thread. class WaitListTest NUMBER_OF_ORDERS = 2 PIPE = File.expand_path("~/tmp/wl_pipe") def setup `rm -f #{PIPE}` `mkfifo #{PIPE}` end def test_registering_last_race term_count = 0 responses = [] pids = [] NUMBER_OF_ORDERS.times do |i| pids << Process.fork do sleep 0.1 + (0.1 * i) 10.times do |a| File.open(PIPE, "w") do |pipe| sleep 0.1 pipe.puts "Fork #{i} - #{a}" end end File.open(PIPE, "w") do |pipe| sleep 0.1 pipe.puts "DONE" end end end pipe = File.open(PIPE, "r") while term_count < NUMBER_OF_ORDERS # File.open(PIPE, "r") do |pipe| val = pipe.gets case val when /DONE/ term_count += 1 when nil puts "pipe closed" # need this too else responses << val end # end end pids.each do |pid| Process.waitpid(pid) end puts responses.sort puts responses.count end end wlt = WaitListTest.new wlt.setup wlt.test_registering_last_race