From 3fb51aec5ba7decffdfc32e540262aaae6167a95 Mon Sep 17 00:00:00 2001 From: nagachika Date: Sun, 5 Sep 2021 14:12:20 +0900 Subject: [PATCH] merge revision(s) bbedd29b6e98ef6e3fc2ce2b358d2b509b7cd1bb: [Backport #18117] [Bug #18117] Fix Ractor race condition with GC rb_objspace_reachable_objects_from requires that the GC not be active. Since the Ractor barrier is not executed for incremental sweeping, Ractor may call rb_objspace_reachable_objects_from after sweeping has started to share objects. This causes a crash that looks like the following: ``` :627: [BUG] rb_objspace_reachable_objects_from() is not supported while during_gc == true ``` Co-authored-by: Vinicius Stock --- bootstraptest/test_ractor.rb | 15 +++++++++++++++ ractor.c | 12 ++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) --- bootstraptest/test_ractor.rb | 15 +++++++++++++++ ractor.c | 12 ++++++++++-- version.h | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index cbf58383c7..f733877319 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1379,4 +1379,19 @@ assert_equal "ok", %q{ end } +# Can yield back values while GC is sweeping [Bug #18117] +assert_equal "ok", %q{ + workers = (0...8).map do + Ractor.new do + loop do + 10_000.times.map { Object.new } + Ractor.yield Time.now + end + end + end + + 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) } + "ok" +} + end # if !ENV['GITHUB_WORKFLOW'] diff --git a/ractor.c b/ractor.c index df9cbc307a..7d6fec76e0 100644 --- a/ractor.c +++ b/ractor.c @@ -2325,7 +2325,11 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data) .stop = false, .data = data, }; - rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d); + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d); + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); if (d.stop) return 1; } break; @@ -2635,7 +2639,11 @@ static int obj_refer_only_shareables_p(VALUE obj) { int cnt = 0; - rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt); + RB_VM_LOCK_ENTER_NO_BARRIER(); + { + rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt); + } + RB_VM_LOCK_LEAVE_NO_BARRIER(); return cnt == 0; } diff --git a/version.h b/version.h index 7f9cb6ada6..44efd8ff67 100644 --- a/version.h +++ b/version.h @@ -12,7 +12,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 3 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 127 +#define RUBY_PATCHLEVEL 128 #define RUBY_RELEASE_YEAR 2021 #define RUBY_RELEASE_MONTH 9