I am trying to understand how the IO.pipe in Ruby works, In the example below, I send data to the io pipe and close the stream after I finish sending the data. In a child process, I read the data using the readpartial method. According to the docs readpartial should raise EOFError when the stream is closed, but I end up with a blocked process instead, Am I understanding it right?
# ruby 2.6.3
r, w = IO.pipe
pid = fork do
loop do
puts r.readpartial(1024)
sleep 0.1
rescue EOFError
puts "End of File"
break
end
end
1000.times do |t|
w.write "xyz #{t}"
end
w.close
Process.wait(pid)
You need to close the write end of the pipe in the child as well as in the parent.
After you fork you effectively have two write ends and two read ends to the pipe. When you close the write end in the parent the write end in the child is still open, so the call to readpartial
will block.
You just need to call w.close
immediately after forking in the child:
pid = fork do
w.close
loop do
#...
You would normally also immediately close the read end in the parent after forking (although in this case it doesn’t really matter):
pid = fork do
#...
end
r.close