redirecting stdin for 3. party program

T

Thomas Secret

OS: Debian Lenny
Ruby version: 1.8.7.72-3lenny1

==Code==

stdin_read,stdin_write=IO.pipe
pid=fork
if !pid
#$stdin.reopen("/home/admin/.bashrc")
stdin_write.close
$stdin.reopen(stdin_read)

a=gets
puts "ruby child: got '#{a}'"
system("echo bash; mawk '{print \"bash child: got \"$0;exit}'")
exit!
end

stdin_read.close
sleep 1
stdin_write.puts "word1"
sleep 1
stdin_write.puts "word2"
sleep 1
puts "parent: before wait"
Process.wait(pid)
puts "parent: after wait"

==/Code==

=Expected result:=

ruby child: got 'ruby word1
'
bash
bash child: got 'ruby word2
'
parent: before wait
parent: after wait

=Actual result:=
ruby child: got 'word1
'
bash
parent: before wait

->after the line 'parent: before wait' has been printed, the program
hangs.

It gets even more interesting if I comment out all the pipe related
stuff and instead redirect $stdin of the child to a file (the line
'$stdin.reopen("/home/admin/.bashrc"):
-I still only get output for 'ruby child', none for 'bash child' -
however it finishes instead of hanging. Perhaps ruby buffers more stdin
than the single 'gets' returns? Multiple 'gets' do work correctly.
-If I comment out the 'gets', it works! So the subshell started by
'system' DOES get the redirected stdin...

=Program that works=
pid=fork
if !pid
$stdin.reopen("/home/admin/.bashrc")

exec("echo bash; mawk '{print \"bash child: got \"$0;exit}'")
exit!
end

puts "parent: before wait"
Process.wait(pid)
puts "parent: after wait"

=Output=
bash
bash child: got # ~/.bashrc: executed by bash(1) for non-login shells.
parent: before wait
parent: after wait


So: What is going wrong when redirecting it to a pipe?
I tried playing around with Kernel.select and replacing system with
exec, but neither changed the result in the least.
I also looked through the implementation of popen4, but can't spot
anything done differently there. Maybe I've already looked at my own
code for to long to spot something obvious though.

So please: Can anyone provide me with a good hint?
 
C

Caleb Clausen

OS: Debian Lenny
Ruby version: 1.8.7.72-3lenny1

==Code==

stdin_read,stdin_write=IO.pipe
pid=fork
if !pid
#$stdin.reopen("/home/admin/.bashrc")
stdin_write.close
$stdin.reopen(stdin_read)

a=gets
puts "ruby child: got '#{a}'"
system("echo bash; mawk '{print \"bash child: got \"$0;exit}'")
exit!
end

stdin_read.close
sleep 1
stdin_write.puts "word1"
sleep 1
stdin_write.puts "word2"
sleep 1
puts "parent: before wait"
Process.wait(pid)
puts "parent: after wait"

==/Code==

=Expected result:=

ruby child: got 'ruby word1
'
bash
bash child: got 'ruby word2
'
parent: before wait
parent: after wait

=Actual result:=
ruby child: got 'word1
'
bash
parent: before wait

->after the line 'parent: before wait' has been printed, the program
hangs.

I've deliberately forgotten all the awk I ever knew, so I modified
your program to use ruby where you had mawk, and it appears to work. I
trust that I have correctly translated the intention of your original
mawk script... Basically, I replaced the system line with:
system("echo bash; ruby -e 'print \"bash child: got \"+readline;exit'")

And I see this output:
ruby child: got 'word1
'
bash
bash child: got word2
parent: before wait
parent: after wait

With your original mawk line, I see the same behavior you do. I'd
suspect a buffering problem, but inserting a flush after puts of word2
doesn't change anything.

However, when I close the handle stdin_write after writing word2, it
does work, even with mawk. Perhaps mawk is waiting for its stdin to
close before it does anything?
 
T

Thomas Secret

Thank you thank you thank you :)

Buffering by mawk simply wasn't something that crossed my mind at all.
With your ruby line it walks flawlessly.

For anyone interested: mawk needs the Option "-W interactive" do process
input as it arrives...

And I dumbly and persistently searched for the problem on the ruby
side...

Thanks again - solved!
 
R

Robert Klemme

2010/6/3 Thomas Secret said:
Thank you thank you thank you :)

Buffering by mawk simply wasn't something that crossed my mind at all.
With your ruby line it walks flawlessly.

For anyone interested: mawk needs the Option "-W interactive" do process
input as it arrives...

And I dumbly and persistently searched for the problem on the ruby
side...

Thomas, why do you use IO.pipe and fork instead of IO.popen or Open3.popen3?

Kind regards

robert
 

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

No members online now.

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top