mirror of
https://github.com/ruby/ruby.git
synced 2026-08-08 15:08:11 +08:00
ractor: lock the owner when Port#closed? is queried from another Ractor
ractor_closed_port_p asserts the owning ractor's lock is held for foreign access and reads sync.ports via st_lookup, but Ractor::Port#closed? (ractor_port_closed_p) called it without the lock. From a foreign Ractor this tripped the assertion and raced the owner's st_insert/st_delete on the ports table. Take the ractor lock for foreign queries, like every other foreign reader. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bf02cf1aae
commit
10e53afd4e
Notes:
git
2026-07-03 03:25:21 +00:00
@ -144,13 +144,27 @@ static VALUE
|
||||
ractor_port_closed_p(rb_execution_context_t *ec, VALUE self)
|
||||
{
|
||||
const struct ractor_port *rp = RACTOR_PORT_PTR(self);
|
||||
rb_ractor_t *r = rp->r;
|
||||
bool closed;
|
||||
|
||||
if (ractor_closed_port_p(ec, rp->r, rp)) {
|
||||
return Qtrue;
|
||||
if (rb_ec_ractor_ptr(ec) == r) {
|
||||
/* The owner's threads are serialized by the ractor GVL, so the ports
|
||||
* table can't change under this lookup. */
|
||||
closed = ractor_closed_port_p(ec, r, rp);
|
||||
}
|
||||
else {
|
||||
return Qfalse;
|
||||
/* A foreign Ractor races the owner's st_insert/st_delete on the ports
|
||||
* table; take the lock like every other foreign reader. ractor_closed_port_p
|
||||
* asserts the lock is held for foreign access, and Port#closed? was the
|
||||
* only path reaching it without the lock. */
|
||||
RACTOR_LOCK(r);
|
||||
{
|
||||
closed = ractor_closed_port_p(ec, r, rp);
|
||||
}
|
||||
RACTOR_UNLOCK(r);
|
||||
}
|
||||
|
||||
return closed ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user