I'm trying to understand IO.popen when its command is "-"
which starts a new Ruby interpreter.
There is not much material about this subject, and I'm getting slowly through them, mainly because of me as I only code for fun.
As far as I have understood when IO.popen("-", "w+") {|f| ...}
is invoked - that's with a block - that block will be run by both the parent and the child process. The difference is that the parent process will get an IO object as a result, but the child gets only a Nil. That's easy, I need to check |f|
in the block and when it is Nil, execution is in the child process, when it is not nil, execution is in the parent. So I have to write both code for parent and child separated by if
.
This time it helps me to understand the problem, that the block is part of the IO.popen command.
I have this code:
pipe = IO.popen("-","w+")
# puts "This line will break functionality if uncommented"
if pipe != nil then
pipe.puts "PID: #{Process.pid}"
$stderr.puts "Parent from child: #{pipe.gets.chomp}"
else
$stderr.puts "Child PID: #{Process.pid} and Parent #{gets.chomp}"
puts "M'kay"
end
Questions:
- What decides which process runs first? If they were to append a file would it be vulnerable to race condition?
- Why the 2nd line breaks the code? The
pipe = IO.popen...
command shouldn't be related to theif..else..end
block, yet they are. For mepipe
is a file handle (like in old Turbo Pascal) which is first definded somewhere, then manipulated elsewhere.