Issue #7220 has been updated by brixen (Brian Ford).


If StringIO manifests this behavior as a copy of IO's behavior, both should be consider bugs.

RubySpec has a quarantined spec for this behavior in IO with a comment stating that there are platform incompatibilities with this IO "state aliasing": https://github.com/rubyspec/rubyspec/blob/master/core/io/dup_spec.rb#L34-54

IO#dup creates an instance with a different underlying fd (#fileno): https://github.com/rubyspec/rubyspec/blob/master/core/io/dup_spec.rb#L30-32

There is no other Ruby core class that causes aliasing when calling #dup. String#dup, for example, is called in code precisely to create a new String so the original would not be mutated.

That IO and StringIO do cause this aliasing is a deviation from the typical behavior of #dup, makes no sense, and is not at all required. It's perfectly possible to do the following:

sasha:rubinius brian$ cat foobar.txt 
123456
sasha:rubinius brian$ irb
1.9.3p286 :001 > a = File.open("foobar.txt", "r")
 => #<File:foobar.txt> 
1.9.3p286 :002 > b = File.open("foobar.txt", "r")
 => #<File:foobar.txt> 
1.9.3p286 :003 > a.getc
 => "1" 
1.9.3p286 :004 > a.pos
 => 1 
1.9.3p286 :005 > b.pos
 => 0 
1.9.3p286 :006 > b.getc
 => "1" 
1.9.3p286 :007 > a.fileno
 => 5 
1.9.3p286 :008 > b.fileno
 => 6 
1.9.3p286 :009 > c = b.dup
 => #<File:foobar.txt> 
1.9.3p286 :010 > c.fileno
 => 7 

Thanks,
Brian
----------------------------------------
Bug #7220: StringIO#initialize_copy causes aliasing between the objects
https://bugs.ruby-lang.org/issues/7220#change-31627

Author: brixen (Brian Ford)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin10.8.0]


Calling StringIO#initialize_copy causes the two objects to share the position, and eof status.

Is this a bug?

sasha:rubinius brian$ irb
1.9.3p286 :001 > require 'stringio'
 => true 
1.9.3p286 :002 > a = StringIO.new "abcdefuq"
 => #<StringIO:0x00000101016a88> 
1.9.3p286 :003 > b = StringIO.new
 => #<StringIO:0x00000101010728> 
1.9.3p286 :004 > b.send :initialize_copy, a
 => #<StringIO:0x00000101010728> 
1.9.3p286 :005 > a.pos
 => 0 
1.9.3p286 :006 > b.pos
 => 0 
1.9.3p286 :007 > b.getc
 => "a" 
1.9.3p286 :008 > a.pos
 => 1 
1.9.3p286 :009 > a.getc
 => "b" 
1.9.3p286 :010 > b.pos
 => 2 
1.9.3p286 :011 > b.read
 => "cdefuq" 
1.9.3p286 :012 > a.eof?
 => true 

Thanks,
Brian


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