IO.pipe trick?

Hi all,

I need someone shed some light on the following problem.

Here is the culprit script:

···

#--------------------------
output = IO.pipe
old_out = $defout.dup
old_out.sync = true
$defout = output[1]
thread = Thread.new {
old_out.puts("@@@@ 1")
while not output[0].eof?
old_out.puts("@@@@ 2")
select([output[0]])
old_out.write(output[0].read)
end
output[0].close
}
puts cat #{ARGV[0]}
output[1].close
thread.join
#--------------------------

Try this script with a text file for the first argument:

  • if the file’s size is less than - say - 8 ko, the script works fine.
  • if the file’s size is more than - say - 10 ko, ruby hangs on the
    while statement.
    What could be the reason for this behavior ?

Thanks in advance.
_gilles.

Hi,

“Gilles Filippini” gilles.filippini@free.fr wrote in message
news:3D30AAF9.96186571@free.fr

Hi all,

I need someone shed some light on the following problem.

Here is the culprit script:
#--------------------------
output = IO.pipe
old_out = $defout.dup
old_out.sync = true
$defout = output[1]
thread = Thread.new {
old_out.puts("@@@@ 1")
while not output[0].eof?
old_out.puts("@@@@ 2")
select([output[0]])
old_out.write(output[0].read)
end
output[0].close
}
puts cat #{ARGV[0]}
output[1].close
thread.join
#--------------------------

Try this script with a text file for the first argument:

  • if the file’s size is less than - say - 8 ko, the script works fine.
  • if the file’s size is more than - say - 10 ko, ruby hangs on the
    while statement.
    What could be the reason for this behavior ?

It’s probably beause pipe’s buffer size is 8192 bytes

Try this:

···

===============================
output = IO.pipe
old_out = $defout.dup
old_out.sync = true
$defout = output[1]
output[1].sync = true
thread = Thread.new {
old_out.puts("@@@@ 1")
while not output[0].eof?
old_out.puts("@@@@ 2")
select([output[0]])
old_out.write(output[0].read)
end
output[0].close
}
cat #{ARGV[0]}.each_byte {|x| print x.chr}
output[1].close
thread.join

Thanks in advance.
_gilles.

Park Heesob

Park Heesob wrote:

Hi,

“Gilles Filippini” gilles.filippini@free.fr wrote in message
news:3D30AAF9.96186571@free.fr

Hi all,

I need someone shed some light on the following problem.

Here is the culprit script:
#--------------------------
output = IO.pipe
old_out = $defout.dup
old_out.sync = true
$defout = output[1]
thread = Thread.new {
old_out.puts("@@@@ 1")
while not output[0].eof?
old_out.puts("@@@@ 2")
select([output[0]])
old_out.write(output[0].read)
end
output[0].close
}
puts cat #{ARGV[0]}
output[1].close
thread.join
#--------------------------

Try this script with a text file for the first argument:

  • if the file’s size is less than - say - 8 ko, the script works fine.
  • if the file’s size is more than - say - 10 ko, ruby hangs on the
    while statement.
    What could be the reason for this behavior ?

It’s probably beause pipe’s buffer size is 8192 bytes

Try this:

output = IO.pipe
old_out = $defout.dup
old_out.sync = true
$defout = output[1]
output[1].sync = true
thread = Thread.new {
old_out.puts("@@@@ 1")
while not output[0].eof?
old_out.puts("@@@@ 2")
select([output[0]])
old_out.write(output[0].read)
end
output[0].close
}
cat #{ARGV[0]}.each_byte {|x| print x.chr}
output[1].close
thread.join

Yes, it works. But it it far too slow. Moreover, I intend to use this
scheme to redirect standard output. Thus I shouldn’t touch the cat
statement.

Anyway, looking at the man pages for write(2) and fcntl(2), I’ve found:

require "fcntl"
output[1].fcntl(Fcntl::F_SETFL, File::NONBLOCK)

And that works great!
Thanks for your answer which gave me the idea to look at those man
pages.

_gilles.

Hi,

nonblock.diff.gz (1.06 KB)

···

At Sun, 14 Jul 2002 17:21:37 +0900, Gilles Filippini wrote:

Anyway, looking at the man pages for write(2) and fcntl(2), I’ve found:

require “fcntl”
output[1].fcntl(Fcntl::F_SETFL, File::NONBLOCK)

I guess it doesn’t work by raising Errno::EWOULDBLOCK.
Currently, no way to know how many bytes are read/written in
that case. Should ruby handle EWOULDBLOCK?