Search code examples
rubystdoutstdininteractionchild-process

ruby - interact with never-end child process


I wonder how can I interact with never-ending(eternal looping) child process.

source code of loop_puts.rb, child process :

loop do
    str = gets
    puts str.upcase
end

main.rb :

Process.spawn("ruby loop_puts.rb",{:out=>$stdout, :in=>$stdin})

I want to put some letter, not by my hand typing, and get result(not previous result) in variable.

how can I do this?

thanks


Solution

  • There are a number of ways to do this and it's hard to recommend one without more context.

    Here's one way using a forked process and a pipe:

    # When given '-' as the first param, IO#popen forks a new ruby interpreter.  
    # Both parent and child processes continue after the return to the #popen 
    # call which returns an IO object to the parent process and nil to the child.
    pipe = IO.popen('-', 'w+')
    if pipe
      # in the parent process
      %w(please upcase these words).each do |s|
        STDERR.puts "sending:  #{s}"
        pipe.puts s   # pipe communicates with the child process
        STDERR.puts "received: #{pipe.gets}"
      end
      pipe.puts '!quit'  # a custom signal to end the child process
    else
      # in the child process
      until (str = gets.chomp) == '!quit'
        # std in/out here are connected to the parent's pipe
        puts str.upcase
      end
    end
    

    Some documentation for IO#popen here. Note that this may not work on all platforms.

    Other possible ways to approach this include Named Pipes, drb, and message queues.