diff options
author | Koichi Sasada <ko1@atdot.net> | 2022-02-14 16:10:18 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2022-02-14 17:17:55 +0900 |
commit | 76e594d5157bd763636adb096d4aa06688ac03ac (patch) | |
tree | a0f3d521db115f766c647a2686a08f39a1cc9817 | |
parent | 838031170c10471fc88ff43133b3b2a2d0c8aa75 (diff) | |
download | ruby-76e594d5157bd763636adb096d4aa06688ac03ac.tar.gz |
fix GC event synchronization
(1) gc_verify_internal_consistency() use barrier locking
for consistency while `during_gc == true` at the end
of the sweep on `RGENGC_CHECK_MODE >= 2`.
(2) `rb_objspace_reachable_objects_from()` is called without
VM synchronization and it checks `during_gc != true`.
So (1) and (2) causes BUG because of `during_gc == true`.
To prevent this error, wait for VM barrier on `during_gc == false`
and introduce VM locking on `rb_objspace_reachable_objects_from()`.
http://ci.rvm.jp/results/trunk-asserts@phosphorus-docker/3830088
-rw-r--r-- | gc.c | 36 |
1 files changed, 22 insertions, 14 deletions
@@ -5722,10 +5722,6 @@ gc_sweep_finish(rb_objspace_t *objspace) gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_SWEEP, 0); gc_mode_transition(objspace, gc_mode_none); - -#if RGENGC_CHECK_MODE >= 2 - gc_verify_internal_consistency(objspace); -#endif } static int @@ -9340,6 +9336,14 @@ gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_l mjit_gc_exit_hook(); gc_exit_clock(objspace, event); RB_VM_LOCK_LEAVE_LEV(lock_lev); + +#if RGENGC_CHECK_MODE >= 2 + if (event == gc_enter_event_sweep_continue && gc_mode(objspace) == gc_mode_none) { + GC_ASSERT(!during_gc); + // sweep finished + gc_verify_internal_consistency(objspace); + } +#endif } static void * @@ -11226,19 +11230,23 @@ rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void * { rb_objspace_t *objspace = &rb_objspace; - if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true"); + RB_VM_LOCK_ENTER(); + { + if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true"); - if (is_markable_object(objspace, obj)) { - rb_ractor_t *cr = GET_RACTOR(); - struct gc_mark_func_data_struct mfd = { - .mark_func = func, - .data = data, - }, *prev_mfd = cr->mfd; + if (is_markable_object(objspace, obj)) { + rb_ractor_t *cr = GET_RACTOR(); + struct gc_mark_func_data_struct mfd = { + .mark_func = func, + .data = data, + }, *prev_mfd = cr->mfd; - cr->mfd = &mfd; - gc_mark_children(objspace, obj); - cr->mfd = prev_mfd; + cr->mfd = &mfd; + gc_mark_children(objspace, obj); + cr->mfd = prev_mfd; + } } + RB_VM_LOCK_LEAVE(); } struct root_objects_data { |