[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>
This commit is contained in:
Peter Zhu 2021-08-17 09:38:40 -04:00
Родитель b62ed309f0
Коммит bbedd29b6e
2 изменённых файлов: 25 добавлений и 2 удалений

Просмотреть файл

@ -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;
}