summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ruby/src/IceRuby/Types.cpp18
1 files changed, 16 insertions, 2 deletions
diff --git a/ruby/src/IceRuby/Types.cpp b/ruby/src/IceRuby/Types.cpp
index fb9aefe3ce8..324f8778793 100644
--- a/ruby/src/IceRuby/Types.cpp
+++ b/ruby/src/IceRuby/Types.cpp
@@ -1853,7 +1853,18 @@ IceRuby::DictionaryInfo::unmarshal(Ice::InputStream* is, const UnmarshalCallback
//
keyType->unmarshal(is, keyCB, Qnil, 0, false);
assert(!NIL_P(keyCB->key));
-
+ if (valueType->usesClasses())
+ {
+ // Temporarily set the entry with a Qnil value to ensure the key is not GC
+ // while unmarshaling a value class
+ if (RB_TYPE_P(keyCB->key, T_STRING))
+ {
+ // For string keys create a frozen string to ensure that the key used
+ // in the map matches the one keep in the closure
+ keyCB->key = rb_str_new_frozen(keyCB->key);
+ }
+ callRuby(rb_hash_aset, hash, keyCB->key, Qnil);
+ }
//
// The callback will set the dictionary entry with the unmarshaled value,
// so we pass it the key.
@@ -2744,7 +2755,10 @@ IceRuby::ReadObjectCallback::invoke(const Ice::ObjectPtr& p)
ex.expectedType = _info->id;
throw ex;
}
-
+#ifndef NDEBUG
+ // With debug builds we force a GC to ensure that all data members are correctly keep alive.
+ rb_gc();
+#endif
_cb->unmarshaled(obj, _target, _closure);
}
else