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