mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
Change bmethod defined_ractor to use id instead
When defining a bmethod, we recorded the current Ractor's object in the method. However that was never marked and so could be GC'd and reused by a future Ractor. Instead we can use the Ractor's id, which we expect to be unique forever. Co-authored-by: Luke Gruber <luke.gru@gmail.com>
This commit is contained in:
parent
de2c2bd60f
commit
1d3fe2c382
Notes:
git
2025-12-04 21:26:16 +00:00
@ -2413,3 +2413,28 @@ assert_equal 'ok', <<~'RUBY'
|
||||
:ok
|
||||
end
|
||||
RUBY
|
||||
|
||||
# When creating bmethods in Ractors, they should only be usable from their
|
||||
# defining ractor, even if it is GC'd
|
||||
assert_equal 'ok', <<~'RUBY'
|
||||
CLASSES = 1000.times.map do
|
||||
Ractor.new do
|
||||
Class.new do
|
||||
define_method(:foo) {}
|
||||
end
|
||||
end
|
||||
end.map(&:value).freeze
|
||||
|
||||
any = 1000.times.map do
|
||||
Ractor.new do
|
||||
CLASSES.any? do |klass|
|
||||
begin
|
||||
klass.new.foo
|
||||
true
|
||||
rescue RuntimeError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end.map(&:value).none? && :ok
|
||||
RUBY
|
||||
|
||||
2
method.h
2
method.h
@ -167,7 +167,7 @@ typedef struct rb_method_refined_struct {
|
||||
typedef struct rb_method_bmethod_struct {
|
||||
VALUE proc; /* should be marked */
|
||||
struct rb_hook_list_struct *hooks;
|
||||
VALUE defined_ractor;
|
||||
rb_serial_t defined_ractor_id;
|
||||
} rb_method_bmethod_t;
|
||||
|
||||
enum method_optimized_type {
|
||||
|
||||
@ -4121,7 +4121,7 @@ vm_call_bmethod_body(rb_execution_context_t *ec, struct rb_calling_info *calling
|
||||
VALUE procv = cme->def->body.bmethod.proc;
|
||||
|
||||
if (!RB_OBJ_SHAREABLE_P(procv) &&
|
||||
cme->def->body.bmethod.defined_ractor != rb_ractor_self(rb_ec_ractor_ptr(ec))) {
|
||||
cme->def->body.bmethod.defined_ractor_id != rb_ractor_id(rb_ec_ractor_ptr(ec))) {
|
||||
rb_raise(rb_eRuntimeError, "defined with an un-shareable Proc in a different Ractor");
|
||||
}
|
||||
|
||||
@ -4144,7 +4144,7 @@ vm_call_iseq_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct
|
||||
VALUE procv = cme->def->body.bmethod.proc;
|
||||
|
||||
if (!RB_OBJ_SHAREABLE_P(procv) &&
|
||||
cme->def->body.bmethod.defined_ractor != rb_ractor_self(rb_ec_ractor_ptr(ec))) {
|
||||
cme->def->body.bmethod.defined_ractor_id != rb_ractor_id(rb_ec_ractor_ptr(ec))) {
|
||||
rb_raise(rb_eRuntimeError, "defined with an un-shareable Proc in a different Ractor");
|
||||
}
|
||||
|
||||
|
||||
@ -1020,7 +1020,7 @@ rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *de
|
||||
}
|
||||
case VM_METHOD_TYPE_BMETHOD:
|
||||
RB_OBJ_WRITE(me, &def->body.bmethod.proc, (VALUE)opts);
|
||||
RB_OBJ_WRITE(me, &def->body.bmethod.defined_ractor, rb_ractor_self(GET_RACTOR()));
|
||||
def->body.bmethod.defined_ractor_id = rb_ractor_id(rb_ec_ractor_ptr(GET_EC()));
|
||||
return;
|
||||
case VM_METHOD_TYPE_NOTIMPLEMENTED:
|
||||
setup_method_cfunc_struct(UNALIGNED_MEMBER_PTR(def, body.cfunc), (VALUE(*)(ANYARGS))rb_f_notimplement_internal, -1);
|
||||
@ -1060,7 +1060,6 @@ method_definition_reset(const rb_method_entry_t *me)
|
||||
break;
|
||||
case VM_METHOD_TYPE_BMETHOD:
|
||||
RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.proc);
|
||||
RB_OBJ_WRITTEN(me, Qundef, def->body.bmethod.defined_ractor);
|
||||
/* give up to check all in a list */
|
||||
if (def->body.bmethod.hooks) rb_gc_writebarrier_remember((VALUE)me);
|
||||
break;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user