Issue #5237 has been updated by Motohiro KOSAKI.


If you are reading following paragraph, 

> *  At end of file, it returns <code>nil</code> or <code>""</code>
> *  depend on <i>length</i>.
> *  <code><i>ios</i>.read()</code> and
> *  <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
> *  <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.

you have to read following paragraph too, I think.

> *  If <i>length</i> is a positive integer,
> *  it try to read <i>length</i> bytes without any conversion (binary mode).
> *  It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
> *  <code>nil</code> means it met EOF at beginning.

*AT BEGINNING*

Thus, positive length destination buffer and returning nil are exclusive. Now, I don't think
we need doc fix.

but I'm not talking about a behavior change. I have no strong opinion. It's another story. I'm waiting akr-san's response.


----------------------------------------
Bug #5237: IO.copy_stream calls #read on an object infinitely many times
http://redmine.ruby-lang.org/issues/5237

Author: Brian Ford
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 
ruby -v: -


The code for IO.copy_stream appears to support passing any object that implements #readpartial or #read. For example, passing an instance of StringIO works just fine:

sasha:rubinius2.0 brian$ irb
ruby-1.9.2-p290 :001 > puts RUBY_DESCRIPTION
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0]
 => nil 
ruby-1.9.2-p290 :002 > require 'stringio'
 => true 
ruby-1.9.2-p290 :003 > s = StringIO.new "this is a test"
 => #<StringIO:0x00000100851190> 
ruby-1.9.2-p290 :004 > IO.copy_stream s, "copy_stream_stringio"
 => 14 
ruby-1.9.2-p290 :005 > IO.read "copy_stream_stringio"
 => "this is a test" 
ruby-1.9.2-p290 :006 > 

However, passing an object that implements eg #read according to the specification of IO#read, causes IO.copy_stream to endlessly call #read on the object:

class A
  def initialize
    @count = 0
  end

  def read(bytes, buffer)
    print "read: #{@count += 1}\r"
    buffer.replace "this is a test"
    return nil
  end
end

a = A.new
IO.copy_stream a, "copy_stream_test"

ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0]
copy_stream_bug.rb:7:in `write': Interrupt
	from copy_stream_bug.rb:7:in `print'
	from copy_stream_bug.rb:7:in `read'
	from copy_stream_bug.rb:14:in `copy_stream'
	from copy_stream_bug.rb:14:in `<main>'

Thanks,
Brian


-- 
http://redmine.ruby-lang.org