"RuntimeError: can't add a new key into hash during iteration" error on test-all of objspace
Now, some platforms have the following errors on "test-all TESTS=objspace".
RuntimeError: can't add a new key into hash during iteration
ruby -v: ruby 2.1.0dev (2013-12-15 trunk 44222) [x64-mswin64_110]
This problem is because of an issue of "ObjectSpace.reachable_objects_from_root".
This method traverse all objects and insert it into a hash object to use as Set.
To set hash object, a hash value is solved by the
hash' method and it usesrb_exec_recursive' for some classes. `rb_exec_recursive' generates a hash object
internally and this value is modified accidentally. This is current my assumption.
For example, we track new objects after `ObjectSpace.reachable_objects_from_root'
and avoid collection of such newer objects can solve this issue, but it will introduce
performance impact (but this method is not performance critical, so it can be accepted).
Updated by ko1 (Koichi Sasada) over 6 years ago
- % Done changed from 0 to 100
- Status changed from Open to Closed
This issue was solved with changeset r44241.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
- ext/objspace/objspace.c (reachable_object_from_root_i): use compare_by_identity hash to avoid hash modify problem during iteration. [Bug #9252]
- ext/objspace/objspace.c (reachable_objects_from_root): ditto.
Updated by phasis68 (Heesob Park) over 6 years ago
This issue is not solved with changeset r44241.
Besides, r44241 caused segmentation fault.
I found that this issue is related with the over optimization on Windows.
Here is a workaround patch:
diff --git a/thread.c b/thread.c.new
index 39bb510..6985ee5 100644
@@ -4754,6 +4754,12 @@ ident_hash_new(void)
- the current callee. */
+#if defined(MSC_VER) && defined(_M_AMD64) && _MSC_VER >= 1400
+# pragma optimize("", off)
+# pragma GCC push_options
+# pragma GCC optimize ("O0")
@@ -4774,6 +4780,11 @@ recursive_list_access(void)
+#if defined(_MSC_VER) && defined(_M_AMD64) && _MSC_VER >= 1400
+# pragma optimize("", on)
+# pragma GCC pop_options
- Returns Qtrue iff obj_id (or the pair ) is already