diff options
author | Koichi Sasada <ko1@atdot.net> | 2021-03-31 17:39:40 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2021-03-31 19:18:32 +0900 |
commit | 1fac99afdae2671a9ca86bead5bde4d0e2eff1b4 (patch) | |
tree | 79a9d4ed4ce36b285c410083515e33464ba66fe6 | |
parent | 8b2f2a707de54ad24d787ff0bce67ed8c68cdded (diff) |
skip marking for uninitialized imemo_env.
RUBY_INTERNAL_EVENT_NEWOBJ can expose uninitialized imemo_env
objects and marking it will cause critical error. This patch
skips marking on uninitialized imemo_env.
See: http://rubyci.s3.amazonaws.com/centos7/ruby-master/log/20210329T183003Z.fail.html.gz
Shortest repro-code is provided by mame-san.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4342
-rw-r--r-- | gc.c | 16 | ||||
-rw-r--r-- | test/objspace/test_objspace.rb | 13 |
2 files changed, 23 insertions, 6 deletions
@@ -6266,12 +6266,16 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_env: { const rb_env_t *env = (const rb_env_t *)obj; - GC_ASSERT(env->ep[VM_ENV_DATA_INDEX_ENV] == obj); - GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); - gc_mark_values(objspace, (long)env->env_size, env->env); - VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); - gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); - gc_mark(objspace, (VALUE)env->iseq); + + if (LIKELY(env->ep)) { + // just after newobj() can be NULL here. + GC_ASSERT(env->ep[VM_ENV_DATA_INDEX_ENV] == obj); + GC_ASSERT(VM_ENV_ESCAPED_P(env->ep)); + gc_mark_values(objspace, (long)env->env_size, env->env); + VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED); + gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env)); + gc_mark(objspace, (VALUE)env->iseq); + } } return; case imemo_cref: diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index 841a1e7c2a..1ccee02faa 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -243,6 +243,19 @@ class TestObjSpace < Test::Unit::TestCase GC.enable end + def test_trace_object_allocations_gc_stress + prev = GC.stress + GC.stress = true + + ObjectSpace.trace_object_allocations{ + proc{} + } + + assert true # success + ensure + GC.stress = prev + end + def test_dump_flags info = ObjectSpace.dump("foo".freeze) assert_match(/"wb_protected":true, "old":true/, info) |