[Ironruby-core] IronRuby's Marshal.dump doesn't work with CLR types, or ruby types backed by a CLR type
Orion.Edwards at gallagher.co
Mon Oct 31 22:04:56 EDT 2011
I've updated the pull request as per Tomas' code review comments.
- Removed ISpecialRubyMarshalling interface in favour of keeping the code
all in the Marshal
- Only implement Exception#==, not === and eql?
- Implement proper Exception comparison logic to match MRI
- Change the Marshal#ReadObject code to special-case Exceptions and Ranges
so we don't need to use reflection to set Exception.message and range
- Minor tweaks to some exception classes to pass a couple more Rubyspecs
while I was at it
From: Tomas Matousek <Tomas.Matousek at microsoft.com>
To: "ironruby-core at rubyforge.org" <ironruby-core at rubyforge.org>
Date: 26/10/2011 03:42 p.m.
Subject: Re: [Ironruby-core] IronRuby's Marshal.dump doesn't work
with CLR types, or ruby types backed by a CLR type
Sent by: ironruby-core-bounces at rubyforge.org
I think we should NOT serialize non-Ruby types for now. The implementation
isn?t quite working so I?d prefer we delete all code that deals with
ISerializable, clean up the marshaller and if .NET serialization is needed
in future implement it fully and correctly.
Marshal.dump has to output exactly the same data as CRuby implementation
(for Ruby objects). Otherwise you won?t be able to read data serialized by
CRuby in IronRuby and vice versa.
From: ironruby-core-bounces at rubyforge.org [
mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Orion Edwards
Sent: Tuesday, October 25, 2011 6:22 PM
To: ironruby-core at rubyforge.org
Subject: [Ironruby-core] IronRuby's Marshal.dump doesn't work with CLR
types, or ruby types backed by a CLR type
Backstory: I'm trying to use DRb for some in-house utility code. DRb
itself seems to work fine, but I found that when I misspelled a method
name, instead of reporting back a NoMethodError, the IronRuby process
crashed immediately to the console.
This is using a relatively recent build of IronRuby from Github
Steps to repro:
e = RuntimeError.new 'xyz'
dumped = Marshal.dump e
e2 = Marshal.load dumped
I would expect e2 to be equivalent to e, but instead the process crashes
with this exception
mscorlib:0:in `_InvokeConstructor': Exception has been thrown by the
target of an invocation. (System::Reflection::TargetInvocationException)
from mscorlib:0:in `InvokeConstructor'
from mscorlib:0:in `Invoke'
from (ir):1:in `load'
Note: This also happens with any CLR type eg System::DateTime.
I looked through IronRuby's marshalling code, and it appears that the
behaviour of Marshal.dump and Marshal.load don't align properly.
Marshal.dump is it's own self-contained set of code which essentially
writes data to a BinaryStream.
For ruby types, it ends up writing a series of values in a format that
looks a lot like what I remember CRuby's marshal writing.
For CLR types, this just writes the Type name and no instance data (clr
objects don't have ruby instance variables after all)
Marshal.load does 2 things:
1. Reads any ruby instance variables out into an Attributes dictionary
2. Uses reflection to find any non-public Constructor(SerializationInfo,
StreamingContext) and invoke it.
For ruby types, this finds the protected RubyClass(SerializationInfo,
StreamingContext) ctor, which calls RubyOps.DeserializeObject, which in
turn reads the attributes dictionary and it's all fine.
For CLR types, this finds whatever constructor might exist for the CLR
object, which does whatever it does for that type.
Unfortunately because the data that is getting passed into the CLR
deserialization constructor came from Marshal.dump which has no knowledge
whatsoever of CLR serialization, the whole thing crashes.
I'm no expert on CLR serialization, so I'd really appreciate some comments
on this, as I'm not sure what to do here.
As far as I can guess however, I can see two solutions:
1. Implement Marshal.dump on top of the CLR serialization code so it
matches Marshal.load and should therefore be able to handle CLR types too.
2. Don't allow marshalling of CLR types, and put some special-case code
into any Ruby types that are backed by CLR types (such as Exception) so
these at least can be serialized?
I'm going to have a crack at #1, but I'm not sure how successful this is.
Again, any feedback would be greatly appreciated.
Ironruby-core mailing list
Ironruby-core at rubyforge.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Ironruby-core