IO.popen with Threads

Hi everyone,

I am trying to use IO.popen in order to put and get messages from a
process to its sub-process (according to
class IO - RDoc Documentation).

I am not experimented and I have two questions about:

1/ Do threads are a good choice, for read and write at the same time
(with IO.popen)?
Have you got a simple exemple?

2/ I think IO.popen is useful for asynchrone communication. But when I
just need to send a message from a process to its sub-process, and wait
its answer, how should we do it? (any example is very appreciated)

Many thanks

On 01.03.2010 21:51, Eikichi On wrote:

Hi everyone,

I am trying to use IO.popen in order to put and get messages from a
process to its sub-process (according to
class IO - RDoc Documentation).

I am not experimented and I have two questions about:

1/ Do threads are a good choice, for read and write at the same time
(with IO.popen)?

Yes.

Have you got a simple exemple?

Please see answer to second question.

2/ I think IO.popen is useful for asynchrone communication. But when I
just need to send a message from a process to its sub-process, and wait
its answer, how should we do it? (any example is very appreciated)

reply = IO.popen [“cat”, “-n”], “r+” do |io|
rdr = Thread.new { io.read } # alternative: io.readlines
io.puts “message”, “you”, “want to send”
io.close_write

rdr.value # joins and fetches the result
end

Kind regards

robert

Thank you very much for your answer, Robert. Thanks to your help, I
could start coding. But I have another little problem and I would
appreciate your opinion.

Here is the code I used:

class Test
  def initialize(program)
    while isready?(program) && cool?(program)
      program.puts 'start', 'my name is ...'
      # ...
    end
  end

  protected

  def process_command(program, command)
    begin
      rdr = Thread.new { program.read } # alternative: io.readlines
      program.puts "#{command}"
      program.close_write
      rdr.value # joins and fetches the result
    end
  end

  def isready?(program)
    reply = process_command(program, 'isready')
    reply.chomp.match(/yes_i_am_ready$/)
  end

  def cool?(program)
    reply = process_command(program, 'cool')
    reply.chomp.match(/yes_i_am_cool$/)
  end
end

program = IO.popen(“./program”, “w+”)

a = Test.new(program)
(…)in `write’: not opened for writing (IOError)

As we can see, there is an error when I try to send a message to the
sub-process because of the closure of the stream
(class IO - RDoc Documentation).

I believe that it is not possible to open again a closed stream. Do you
think a good way is to don’t close the stream (except at the very end of
the Ruby script)? or should it be better to change the current code
structure?

Thanks again for any help.

2010/3/2 Eikichi On [email protected]:

     # ...
     rdr.value # joins and fetches the result
   reply.chomp.match(/yes_i_am_cool$/)

(class IO - RDoc Documentation).

I believe that it is not possible to open again a closed stream.

Exactly that is the source of your error.

Do you
think a good way is to don’t close the stream (except at the very end of
the Ruby script)? or should it be better to change the current code
structure?

I would certainly change the structure. I would put the IO.popen
inside the class since you will be writing a class handling a specific
external program - at least that’s what seems to be the case here.

When you close the stream depends on the external program you are
executing. There is no general rule I can give you here.

Note that if you need to deal with multiple requests and responses
from the external process I believe there are a number of tools around
for that already. You should be able to find something by searching
for “ruby expect”.

Kind regards

robert

2010/3/2 Eikichi On [email protected]:

‘are u ready?’ ‘yes_i_am_ready’
‘are u cool?’ ‘yes_i_am_cool’
‘Hello’ ‘foo’
‘my name is …’ ‘bar’

Help me please :o

That’s exactly the “expect” like model. See for example:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/66884

Kind regards

robert

Thank you for your reply very educational, very clear. I have tested
IO#readline instead of IO#read, but once again I’ve got a “write” error.
And I don’t exactly see how to fix it.

I just would like to establish a such communication (according to a
given protocol) like:

Parent message: Child answer:


‘are u ready?’ ‘yes_i_am_ready’
‘are u cool?’ ‘yes_i_am_cool’
‘Hello’ ‘foo’
‘my name is …’ ‘bar’

Help me please :o