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?
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?