IO.popen hangs reading an empty pipe?

P

Payton Swick

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
 
A

ara.t.howard

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.rubyforge.org
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
 
P

Payton Swick

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
 
A

ara.t.howard

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.

you can do anything with session that bash can do - not sure if it'll work for
sendmail or not. should work anywhere you are dealing with stdin/out/err.
- 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.

cheers.


-a
 
J

Joel VanderWerf

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.
 

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

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top