3

The following code works, but if reader and writer are shared resource across parent and child process, why are they closed in the first place?

reader, writer = IO.pipe

fork do
  reader.close
  writer.puts "foobar"
end

writer.close
puts reader.read  

This makes no sense to me, because I think the reader and writer should be closed after the write operation like the following code I made

reader, writer = IO.pipe                                                        

fork do                                                                         
    writer.puts "foobar"                                                  
    writer.close                                                                
end                                                                             
Process.wait                                                                    
puts reader.read                                                                
reader.close       

I don't know why it doesn't work. Can anyone give me an idea?

sawa
  • 165,429
  • 45
  • 277
  • 381
mko
  • 21,334
  • 49
  • 130
  • 191

1 Answers1

3

What is going on is, quoted from Stormier, Jesse. Working with UNIX Processes (http://workingwithunixprocesses.com, 2012) p. 93:

...when the reader calls IO#read it will continue trying to read data until it sees an EOF (aka. end-of-file marker [2]). This tells the reader that no more data will be available for reading.

So long as the writer is still open the reader might see more data, so it waits. By closing the writer before reading it puts an EOF on the pipe so the reader stops reading after it gets the initial data. If you skip closing the writer then the reader will block and continue trying to read indefinitely.

I highly recommend giving his book a read if you are going to be working a lot with IO (including sockets).

As stated in your other question How to maintain the TCP connection using Ruby? you can manually force the buffer to flush using IO#flush or set the buffer to always sync after a write / read, by setting IO#sync= to true.

Community
  • 1
  • 1
Aaron K
  • 6,901
  • 3
  • 34
  • 29