diff options
author | Peter Zhu <peter@peterzhu.ca> | 2021-08-17 09:38:40 -0400 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2021-08-24 09:47:42 -0400 |
commit | bbedd29b6e98ef6e3fc2ce2b358d2b509b7cd1bb (patch) | |
tree | 2eba0389a85fb60b06fc4c2fe9ba6d57e4117ee0 | |
parent | b62ed309f05d248c746279f35f2609f01ea1e4a5 (diff) |
[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:
```
<internal:ractor>:627: [BUG] rb_objspace_reachable_objects_from() is not supported while during_gc == true
```
Co-authored-by: Vinicius Stock <vinicius.stock@shopify.com>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/4755
-rw-r--r-- | bootstraptest/test_ractor.rb | 15 | ||||
-rw-r--r-- | ractor.c | 12 |
2 files changed, 25 insertions, 2 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 28c9e6d90c..01d02dce77 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1418,4 +1418,19 @@ assert_equal "ok", %q{ 'ok' } +# 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'] @@ -2368,7 +2368,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; @@ -2678,7 +2682,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; } |