Why can't open4 read from stdout when the program is waiting for stdin?
I am using the open4
gem and having problems reading from the spawned processes stdout. I开发者_JS百科 have a ruby program, test1.rb
:
print 'hi.' # 3 characters
$stdin.read(1) # block
And another ruby program in the same directory, test2.rb
:
require 'open4'
pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb'
p stdout.read(2) # 2 characters
When I run the second program:
$ ruby test2.rb
It just sits there forever without printing anything. Why does this happen, and what can I do to stop it?
I needed to change test1.rb
to this. I don't know why.
print 'hi.' # 3 characters
$stdout.flush
$stdin.read(1) # block
By default, everything that you print
to stdout or to another file is written into a buffer of Ruby (or the standard C library, which is underneath Ruby). The content of the buffer is forwarded to the OS if one of the following events occurs:
- The buffer gets full.
- You close stdout.
- You have printed a newline sequence (`\n')
- You call
flush
explicitly.
For other files, a flush
is done on other occasions, too, like ftell
.
If you put stdout in unbuffered mode ($stdout.sync = true
), the buffer will not be used.
stderr is unbuffered by default. The reason for doing buffering is efficiency: Aggregating output data in a buffer can save many system call (calls to operating system). System calls are very expensive: They take many hundreds or even thousands of CPU cycles. Avoiding them with a little bit of code and some buffers in user space results in a good speedup.
A good reading on buffering: Why does printf not flush after the call unless a newline is in the format string?
I'm not an expert in process.
From my first sight of API document, the sequence of using open4 is like this: first send text to stdin, then close stdin and lastly read text from stdout.
So. You can the test2.rb
like this
require 'open4'
pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb'
stdin.puts "something" # This line is important
stdin.close # It might be optional, open4 might close itself.
p stdout.read(2) # 2 characters
精彩评论