开发者

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 printto 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜