Bug #9252

"RuntimeError: can't add a new key into hash during iteration" error on test-all of objspace

Added by ko1 (Koichi Sasada) over 6 years ago. Updated over 6 years ago.

Target version:
ruby -v:
ruby -v: ruby 2.1.0dev (2013-12-15 trunk 44222) [x64-mswin64_110]


Now, some platforms have the following errors on "test-all TESTS=objspace".

1) Error:
RuntimeError: can't add a new key into hash during iteration
C:/ko1/src/ruby/trunk/test/objspace/test_objspace.rb:109:in hash'
C:/ko1/src/ruby/trunk/test/objspace/test_objspace.rb:109:in reachable_objects_from_root'

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 uses
rb_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/
index 39bb510..6985ee5 100644
--- a/thread.c
+++ b/
@@ -4754,6 +4754,12 @@ ident_hash_new(void)

  • the current callee. */

+#if defined(MSC_VER) && defined(_M_AMD64) && _MSC_VER >= 1400
+# pragma optimize("", off)
+#elif defined(
+# pragma GCC push_options
+# pragma GCC optimize ("O0")
static VALUE
@@ -4774,6 +4780,11 @@ recursive_list_access(void)
return list;
+#if defined(_MSC_VER) && defined(_M_AMD64) && _MSC_VER >= 1400
+# pragma optimize("", on)
+#elif defined(
+# pragma GCC pop_options


  • Returns Qtrue iff obj_id (or the pair ) is already

Also available in: Atom PDF