Fix ractor move of object with generic ivars (#15056)

This bug was happening only when the `id2ref` table exists. We need
to replace the generic fields before replacing the object id of the
newly moved object.

Fixes [Bug #21664]
This commit is contained in:
Luke Gruber 2025-11-05 12:42:08 -05:00 committed by GitHub
parent 57040636df
commit 54907db8f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-11-05 17:42:39 +00:00
Merged-By: luke-gru <luke.gru@gmail.com>
2 changed files with 15 additions and 3 deletions

View File

@ -1969,6 +1969,19 @@ assert_equal 'ok', %q{
roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
}
# move object with generic ivars and existing id2ref table
# [Bug #21664]
assert_equal 'ok', %q{
obj = [1]
obj.instance_variable_set("@field", :ok)
ObjectSpace._id2ref(obj.object_id) # build id2ref table
ractor = Ractor.new { Ractor.receive }
ractor.send(obj, move: true)
obj = ractor.value
obj.instance_variable_get("@field")
}
# copy object with complex generic ivars
assert_equal 'ok', %q{
# Make Array too_complex

View File

@ -1973,13 +1973,12 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data)
rb_gc_writebarrier_remember(data->replacement);
void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c
rb_gc_obj_id_moved(data->replacement);
if (UNLIKELY(rb_obj_exivar_p(obj))) {
rb_replace_generic_ivar(data->replacement, obj);
}
rb_gc_obj_id_moved(data->replacement);
VALUE flags = T_OBJECT | FL_FREEZE | (RBASIC(obj)->flags & FL_PROMOTED);
// Avoid mutations using bind_call, etc.