# Redirecting stdin for 3. party program

**URL:** <https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593>\
**Category:** Ruby\
**Created:** [June 3, 2010, 5:46pm UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593 "2010-06-03T17:46:50Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [June 3, 2010, 5:46pm UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593/1 "2010-06-03T17:46:50Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [June 3, 2010, 7:18pm UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593/2 "2010-06-03T19:18:55Z")

</div>

One small addendum: I’m not actually interested in reading in something  
via ‘gets’ before launching the external command, I only included it for  
demonstration purposes.  
What I am hoping to get to work is something like the second test case,  
just with stdin coming from a pipe instead of a file.

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [June 3, 2010, 9:04pm UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593/3 "2010-06-03T21:04:07Z")

</div>

On 6/3/10, Thomas S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> $stdin.reopen(stdin_read)
> 
> ```
> 
> sleep 1  
> ruby child: got 'ruby 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?

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [June 3, 2010, 9:17pm UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593/4 "2010-06-03T21:17:14Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![tcsnide](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/eb8c5e/32.png) [@tcsnide](https://www.ruby-forum.com/u/tcsnide)\
**Post date:** [June 7, 2010, 10:12am UTC](https://www.ruby-forum.com/t/redirecting-stdin-for-3-party-program/189593/5 "2010-06-07T10:12:51Z")

</div>

2010/6/3 Thomas S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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
