Project

General

Profile

Bug #1744

Error with Marshal dump/load on a delegated class.

Added by DarKo (Guillaume Delugré) over 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
ruby -v:
ruby 1.9.2dev (2009-11-17 trunk 25805) [i386-darwin9.8.0]
Backport:
[ruby-core:24211]

Description

=begin
Instance variables are not handled when using Marshal with a delegated class.

Here is an example :
on Ruby 1.8, the instance variable @var will be copied fine.
on Ruby 1.9.1, it is set to nil.

It seems to only occur with class inherited from DelegateClass.

==================================
require 'delegate'

class C < DelegateClass(Integer)
attr_accessor :var

def initialize
@var = 1
end
end

c = C.new
p c.var # => 1

d = Marshal.load(Marshal.dump(c))
p d.var # => nil on Ruby 1.9
==================================
=end


Files

ex.rb (195 Bytes) ex.rb Example file DarKo (Guillaume Delugré), 07/09/2009 04:41 AM

History

#1

Updated by yugui (Yuki Sonoda) about 10 years ago

  • Target version set to 1.9.2
  • ruby -v set to ruby 1.9.2dev (2009-11-17 trunk 25805) [i386-darwin9.8.0]

=begin
It seems a possible bug rather than a backport task. It can be reproduced in the trunk version.
=end

#2

Updated by nobu (Nobuyoshi Nakada) about 10 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r26007.
Guillaume, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

#3

Updated by nobu (Nobuyoshi Nakada) about 10 years ago

  • Status changed from Closed to Open

=begin

=end

#4

Updated by marcandre (Marc-Andre Lafortune) about 10 years ago

  • Status changed from Open to Closed

=begin
This issue was solved with changeset r26163.
Guillaume, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

#5

Updated by marcandre (Marc-Andre Lafortune) about 10 years ago

  • Category set to lib

=begin
Fixed also in 1.8 with r26164. This particular example worked in 1.8 because DelegateClass does not return a subclass of Delegator in 1.8, but the same bug existed for SimpleDelegator, for example.

Also added basic RubySpec for this.
=end

#6

Updated by nobu (Nobuyoshi Nakada) about 10 years ago

=begin
Hi,

At Thu, 24 Dec 2009 13:14:43 +0900,
Marc-Andre Lafortune wrote in [ruby-core:27306]:

Fixed also in 1.8 with r26164. This particular example worked
in 1.8 because DelegateClass does not return a subclass of
Delegator in 1.8, but the same bug existed for
SimpleDelegator, for example.

Also added basic RubySpec for this.

This change has broken marshal format comatibility.

$ cat d.rb
require 'delegate'
class A < DelegateClass(Array)
end

$ ruby -v
ruby 1.9.2dev (2009-12-19 trunk 26127) [universal.x86_64-darwin9.0]

$ ./ruby -v
ruby 1.9.2dev (2009-12-23 trunk 26157) [universal.x86_64-darwin9.0]

$ ruby -I. -rd -e 'Marshal.dump(A.new([]), STDOUT)' | ./ruby -I. -rd -e 'p Marshal.load(STDIN)'
/Users/nobu/src/ruby/ruby-1.9.2/src/lib/delegate.rb:195:in marshal_load': undefined methodeach_with_index' for nil:NilClass (NoMethodError)
from -e:1:in load'
from -e:1:in
'

--
Nobu Nakada

=end

#7

Updated by marcandre (Marc-Andre Lafortune) about 10 years ago

  • Status changed from Closed to Open

=begin
On Sun, Dec 27, 2009 at 8:19 PM, Nobuyoshi Nakada nobu@ruby-lang.org wrote:

This change has broken marshal format comatibility.

Indeed.

I can't think of a way to make it backward compatible, but for forward compatibility, how about the following?

diff --git a/lib/delegate.rb b/lib/delegate.rb
index f8a71f1..1516dac 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -184,16 +184,21 @@ class Delegator
# Serialization support for the object returned by __getobj__.
def marshal_dump
[

  • :v2, instance_variables, instance_variables.map{|var| instance_variable_get(var)}, getobj ] end # Reinitializes delegation from a serialized object.
  • def marshal_load(obj)
  • vars, values, obj = obj
  • vars.each_with_index{|var, i| instance_variable_set(var, values[i])}
  • setobj(obj)
  • def marshal_load(data)
  • version, vars, values, obj = data
  • if version == :v2
  • vars.each_with_index{|var, i| instance_variable_set(var, values[i])}
  • setobj(obj)
  • else
  • setobj(data)
  • end end

=end

#8

Updated by marcandre (Marc-Andre Lafortune) about 10 years ago

  • Status changed from Open to Closed

=begin
This issue was solved with changeset r26195.
Guillaume, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF