From: brian ford Date: 2011-08-28T02:33:42+09:00 Subject: [ruby-core:39145] Re: [Ruby 1.9 - Bug #5237] IO.copy_stream calls #read on an object infinitely many times On Sat, Aug 27, 2011 at 3:54 AM, Eric Wong wrote: > > Issue #5237 has been updated by Eric Wong. > > File 0001-avoid-infinite-loop-of-IO.copy_stream.patch added > > The class that implements an IO#read-like method without clearing > the destination buffer on EOF is arguably broken, but infinite > looping is bad, I think. Ah, you are right, it really should replace buffer with "" (according to the code) and return nil according to the docs. Seems more than a little weird, however, to empty the buffer to signal EOF, especially since the buffer argument is optional. Cheers, Brian > > The attached simple patch should fix the issue. �Also available via git: > �git pull git://bogomips.org/ruby.git copy-stream-infinite-loop > > ---------------------------------------- > 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: ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0] > > > 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" > �=> # > 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 `
' > > Thanks, > Brian > > > -- > http://redmine.ruby-lang.org > >