[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Get back data from a child (with exec

Lawrence Oluyede

5/12/2005 8:30:00 PM


What I'm trying to do is to pass some data
to a child process that execute an external process
and get back data from this external process.

---
PATH = "/usr/bin/highlight"
ARGS = "-f -l -t 8 -S %s"
LANG = "rb"

rd, wr = IO.pipe

if fork
# parent
rd.close
$stdout.reopen(wr)
wr.close

fd = File.open("/usr/lib/ruby/1.8/thread.rb")
str = fd.read
$stdout.write str
else
# child
wr.close
$stdin.reopen(rd)
rd.close

params = ARGS % LANG
cmd = "%s %s" % [PATH, params]
exec cmd
end
---

This works but child puts returned data to the standard output
(to the linux shell). I'd like to get back that output in the parent.
How can I do it?

--
Lawrence
http://www.oluyed...
12 Answers

Ara.T.Howard

5/12/2005 9:07:00 PM

0

Lawrence Oluyede

5/13/2005 6:05:00 PM

0

Ara.T.Howard@noaa.gov writes:

> harp:~ > cat a.rb
> IO::popen('-') do |pipe|
> if pipe
> stdout = pipe.read
> puts "parent got <#{ stdout }> from child"
> else
> exec 'echo', '-n', '42'
> end
> end
>
> harp:~ > ruby a.rb
> parent got <42> from child

Works, but there's a problem. If I open the pipe in read/write
mode and exec a program that reads from stdin it doesn't work :(

--
Lawrence
http://www.oluyed...

Ara.T.Howard

5/13/2005 6:38:00 PM

0

Lawrence Oluyede

5/13/2005 7:00:00 PM

0

Ara.T.Howard@noaa.gov writes:

> pipe.close_write

That's what I missed!

> you aren't trying to run a program that requires a tty (like top) are you?

No no...

Thanks a lot!

--
Lawrence
http://www.oluyed...

Lawrence Oluyede

5/13/2005 8:40:00 PM

0


How can I deal with large inputs to an external process
popen driven? With 5k of data sent to its standard
input blocks.

--
Lawrence
http://www.oluyed...

Ara.T.Howard

5/13/2005 8:50:00 PM

0

Lawrence Oluyede

5/13/2005 9:15:00 PM

0

Ara.T.Howard@noaa.gov writes:

> send the data down in a thread
>
> data = IO::read 'huge_file'
> sender = Thread::new(data){data.each{|line| pipe.puts line}}
>
> you'd probably then want a reader to load a thread safe queue with the
> returned data.

That's what I was doing before with popen3, wrap the function with a Thread.
Let me try again

> why don't you want to block?

Cause it hangs the UI (a webpage)

--
Lawrence
http://www.oluyed...

Ilmari Heikkinen

5/13/2005 9:33:00 PM

0


On 13.5.2005, at 23:40, Lawrence Oluyede wrote:

>
> How can I deal with large inputs to an external process
> popen driven? With 5k of data sent to its standard
> input blocks.
>
> --
> Lawrence
> http://www.oluyed...
>

You need to send the data in blocks lequal to the pipe buffer size.
Something like pipe.write(input.read(4096)) until input.eof?

Also, if the external process outputs to its stdout, it will block once
it
has written pipe buffer bytes, so you need to read from the pipe aswell.

So, one thread for writing, one thread for reading.


Btw, maybe popened IOs should do this automatically under covers?

test_popen.rb

d = ' '*32000
IO.popen('cat','r+'){|c|
Thread.new{ c.write(d); c.close_write }
puts c.read.size
}

Here's a way to fix the hang:

class IO
class << self
alias_method :real_popen, :popen
def popen(*args,&block)
io = real_popen(*args)
def io.write(data)
i = wb = 0
(wb += super(data[i,4096]); i+=4096) while i < data.size
wb
end
if block_given?
block.call(io)
else
io
end
end
end
end



Ara.T.Howard

5/13/2005 9:39:00 PM

0

Lawrence Oluyede

5/13/2005 10:50:00 PM

0

Ara.T.Howard@noaa.gov writes:

> ah, why didn't you say so? ;-) that's __exactly__ why i designed my session
> lib - to NOT hang tk apps. it's thread safe so you can do this:

Seems cool but I don't get it work with my own
example. Popen/forks/threads/hangs are causing me a big headache in those
days :D Everything (popen and my own fork based code) seems to work except
when it's behind a web app.

I think I should write a Ruby replacement of the external process

--
Lawrence
http://www.oluyed...