playing with popen again

H

Hal Fulton

Why doesn't this work?

prog1 calls prog2... the latter starts by writing a line, then reading
a line. The former reads first, then writes.

It hangs indefinitely. When I kill prog1, it appears that I interrupted
a gets on each side.

What am I doing that's stupid?

Thanks,
Hal


# prog1
io = IO.popen("ruby prog2.rb","r+")
str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"


#!/usr/local/bin/ruby
# prog2
puts "This is prompt 1"
gets
puts "This is 2nd prompt"
gets
puts "3rd/final prompt"
gets


$ ruby prog1.rb # and then ctl-C
prog1.rb:2:in `gets': Interrupt from prog1.rb:2
prog2.rb:3:in `gets': Interrupt from prog2.rb:3
 
C

Chris Spiegel

It hangs indefinitely. When I kill prog1, it appears that I interrupted
a gets on each side.

# prog1
io = IO.popen("ruby prog2.rb","r+")
str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"

#!/usr/local/bin/ruby
# prog2
puts "This is prompt 1"
gets
puts "This is 2nd prompt"
gets
puts "3rd/final prompt"
gets

This would be a side-effect of buffering. prog2.rb won't be sending
anything over the pipe until it's flushed (standard out is normally
line-buffered when connected to a terminal, but fully buffered when it's
not). If you add $stdout.flush after each puts in your prog2.rb then it
should work as expected.

You can check the status of whether autoflushing is on with IO#sync.
io.sync in prog1.rb should be true, $stdout.sync in prog2.rb should be
false (which means instead of flushing manually, you could do:
$stdout.sync = true in prog2.rb.)

I'm not extremely well-versed in Ruby so please accept my apologies if
this information is more Unix-centric than Ruby-centric.

Chris
 
A

Ara.T.Howard

Why doesn't this work?

prog1 calls prog2... the latter starts by writing a line, then reading
a line. The former reads first, then writes.

It hangs indefinitely. When I kill prog1, it appears that I interrupted
a gets on each side.

What am I doing that's stupid?

Thanks,
Hal


# prog1
io = IO.popen("ruby prog2.rb","r+")
str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"

str = io.gets
puts "got: #{str}"
io.puts "junk"


#!/usr/local/bin/ruby
# prog2
puts "This is prompt 1"
gets
puts "This is 2nd prompt"
gets
puts "3rd/final prompt"
gets


$ ruby prog1.rb # and then ctl-C
prog1.rb:2:in `gets': Interrupt from prog1.rb:2
prog2.rb:3:in `gets': Interrupt from prog2.rb:3

stdout is only line buffered when it's a tty. in the case of an external
process it is completely buffered - you are seeing the operating system chose
not to send the output of prog2 because the buffer has not yet been filled.

~ > cat prog1
io = IO.popen("ruby prog2","r+")
3.times do |i|
print "read #{ i } => "
str = io.gets
puts "<#{ str.inspect }>"
io.puts
end

~ > cat prog2
#
# magic bullet
#
STDOUT.sync = true

3.times do |i|
puts "prompt #{ i }"
gets
end

~ > ruby prog1
read 0 => <"prompt 0\n">
read 1 => <"prompt 1\n">
read 2 => <"prompt 2\n">


cheers.

-a
--
===============================================================================
| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE :: 303.497.6469
| A flower falls, even though we love it; and a weed grows, even though we do
| not love it. --Dogen
===============================================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,823
Latest member
Nadia88

Latest Threads

Top