summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2025-05-23 16:08:51 +0200
committerJean Boussier <jean.boussier@gmail.com>2025-05-23 17:33:17 +0200
commit1435ea7f44f3d781a03054b4055a1ad2f90dd392 (patch)
tree55946492d7201e9ace149012956f1c108c651df5 /variable.c
parent52da5f8bbc705e75d89403df281fcf95d30cbe15 (diff)
Add missing lock for `Module#remove_instance_variable`
We must take a lock to ensure another ractor isn't reading the ivars while we're moving them.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13426
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/variable.c b/variable.c
index fd88849689..5c381f80ba 100644
--- a/variable.c
+++ b/variable.c
@@ -1537,9 +1537,13 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
{
rb_check_frozen(obj);
+ bool locked = false;
+ unsigned int lev = 0;
VALUE val = undef;
if (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) {
IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
+ RB_VM_LOCK_ENTER_LEV(&lev);
+ locked = true;
}
shape_id_t old_shape_id = rb_obj_shape_id(obj);
@@ -1551,6 +1555,9 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
shape_id_t next_shape_id = rb_shape_transition_remove_ivar(obj, id, &removed_shape_id);
if (next_shape_id == old_shape_id) {
+ if (locked) {
+ RB_VM_LOCK_LEAVE_LEV(&lev);
+ }
return undef;
}
@@ -1600,6 +1607,10 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
}
rb_shape_set_shape_id(obj, next_shape_id);
+ if (locked) {
+ RB_VM_LOCK_LEAVE_LEV(&lev);
+ }
+
return val;
too_complex:
@@ -1630,6 +1641,11 @@ too_complex:
}
}
}
+
+ if (locked) {
+ RB_VM_LOCK_LEAVE_LEV(&lev);
+ }
+
return val;
}