[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

IO.popen hangs reading an empty pipe?

Payton Swick

1/30/2006 7:25:00 PM

How does one check a pipe (created using IO.popen) to see if there is
input waiting without using IO#eof or reading from the pipe? Doing
either of these seems to hang forever if the pipe is empty.

Here's an example:

require 'timeout'
IO.popen("cat", "r+") do |pipe|
# pipe.puts "hello world" # Uncomment this to prevent hang below.
Timeout::timeout(2) do
if not pipe.eof? # This will hang if the pipe is empty.
p pipe.getc
end
end
end

-Payton


4 Answers

Ara.T.Howard

1/30/2006 7:39:00 PM

0

Payton Swick

1/30/2006 8:01:00 PM

0

Ah. You're right, of course. I could have sworn that I tried using
pipe.close_write before and the problem remained, but apparently I was
mistaken.

Notes:
- "cat" was just to prove a point - the real issue was with
"sendmail", but it seems to have the same solution. My brief overview
made me think session was not suited for sendmail, but perhaps I was
wrong about that too? I'll check it out.
- the use of timeout was just to allow the test to exit when the hang
occurred. I didn't realize it fails on w32. Is it Timeout that fails,
or just when timeout is combined with IO reads?

Thanks again!
-Payton

ara.t.howard@noaa.gov wrote:
> On Tue, 31 Jan 2006, Payton Swick wrote:
>
>> How does one check a pipe (created using IO.popen) to see if there is
>> input waiting without using IO#eof or reading from the pipe? Doing
>> either of these seems to hang forever if the pipe is empty.
>
>
> harp:~ > cat a.rb
> IO.popen("cat", "r+") do |pipe|
> pipe.puts 42
> pipe.close_write
> puts pipe.read
> end
>
>
> harp:~ > ruby a.rb
> 42
>
>
>
> consider that cat reads stdin until eof is found.
>
>> Here's an example:
>>
>> require 'timeout'
>> IO.popen("cat", "r+") do |pipe|
>> # pipe.puts "hello world" # Uncomment this to prevent hang below.
>
>
> not really - only the first one. continue to read an you'll still
> hang. this
> is because cat is still waiting on more stdin or eof. so you must send
> more or
> close the write end of the pipe to send eof.
>
>> Timeout::timeout(2) do
>
>
> never mix timeout with reads. it fails on windoze - if you care.
>
>> if not pipe.eof? # This will hang if the pipe is empty.
>
>
> because cat is waiting for stdin and is not finsihed - cat will only
> close it's
> stdout when it's done and it's only done when it's stdin has all been read.
> man 1 cat.
>
>> p pipe.getc
>> end
>> end
>> end
>
>
>
> if you are on *nix you'll find my session module much easier to use:
>
> harp:~ > gem install session
> Attempting local installation of 'session'
> Local gem file not found: session*.gem
> Attempting remote installation of 'session'
> Updating Gem source index for: http://gems.rub...
> Successfully installed session-2.4.0
> harp:~ > cat a.rb
> require "rubygems"
> require "session"
> require "stringio"
>
>
> sh = Session::new
>
> stdin = "42"
> stdout = StringIO::new
> stderr = StringIO::new
>
> sh.execute "cat", "stdin" => stdin, "stdout" => stdout, "stderr" =>
> stderr
>
> puts stdout
>
>
> harp:~ > ruby a.rb
> 42
>
>
> session can also be made to be thread-safe (eg use with timeout) if
> needed. see docs for more.
>
>
> kind regards.
>
>
>
> -a


Ara.T.Howard

1/30/2006 8:23:00 PM

0

Joel VanderWerf

1/30/2006 8:29:00 PM

0

ara.t.howard@noaa.gov wrote:
...
>> - the use of timeout was just to allow the test to exit when the hang
>> occurred. I didn't realize it fails on w32. Is it Timeout that
>> fails, or just when timeout is combined with IO reads?
>
> i may have mispoke - you may be able to use a thread and timeout - but
> it very
> easy to block an entire process with io and threads in win... fyi.

I've mixed threads, timeout, and sockets on windows with no problems.
But I haven't done this with pipes...

ISTR that the problem on windows is with terminal io.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407