mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
ractor: guard the port VALUE across receive/send
ractor_port_receive/send derive a raw 'struct ractor_port *rp' from self's embedded (RUBY_TYPED_EMBEDDABLE) data and keep using it across a GC safepoint: receive parks, and send allocates the basket. self is only kept alive movably (rb_gc_mark_movable via the VM stack), so a concurrent GC.compact can relocate the port and leave rp dangling -- the receiver then polls a stale, reused slot's port id forever (a hang of Ractor#value under IO + GC.compact). RB_GC_GUARD(self) keeps self on the machine stack, whose conservative scan pins the port so it cannot move while rp is live.
This commit is contained in:
1 parent
6a098a07e5
commit
fc6ff6fbcc
1 file changed
+4
-1
Notes:
git
2026-07-14 08:33:23 +00:00
+4
-1
@@ -126,7 +126,9 @@ ractor_port_receive(rb_execution_context_t *ec, VALUE self)
|
||||
rb_raise(rb_eRactorError, "only allowed from the creator Ractor of this port");
|
||||
}
|
||||
|
||||
return ractor_receive(ec, rp);
|
||||
VALUE v = ractor_receive(ec, rp);
|
||||
RB_GC_GUARD(self);
|
||||
return v;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
@@ -134,6 +136,7 @@ ractor_port_send(rb_execution_context_t *ec, VALUE self, VALUE obj, VALUE move)
|
||||
{
|
||||
const struct ractor_port *rp = RACTOR_PORT_PTR(self);
|
||||
ractor_send(ec, rp, obj, RTEST(move));
|
||||
RB_GC_GUARD(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user