Reuse `_parent_chan` to unregister from parent-registrar

When the parent actor IS the registrar, reuse the existing parent
channel for `unregister_actor` RPC instead of opening a new connection
via `get_registry()`. This avoids failures when the registrar's listener
socket is already closed during teardown (e.g. UDS transport unlinks the
socket file rapidly).

Deats,
- detect `parent_is_reg` by comparing `_parent_chan.raddr` against
  `reg_addrs` and if matched, create a `Portal(rent_chan)` directly
  instead of `async with get_registry()`.
- rename `failed` -> `failed_unreg` for clarity.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
subint_spawner_backend
Gud Boi 2026-04-14 15:08:22 -04:00
parent 75b07c4b7c
commit 7b04b2cdfc
1 changed files with 42 additions and 8 deletions

View File

@ -1845,13 +1845,46 @@ async def async_main(
and and
not actor.is_registrar not actor.is_registrar
): ):
failed: bool = False failed_unreg: bool = False
rent_chan: Channel|None = actor._parent_chan
# XXX check if the parent IS the registrar so we can
# reuse the existing channel (avoids opening a new
# connection which fails when the listener socket is
# already closed, e.g. UDS transport unlinks the socket
# file during teardown).
parent_is_reg: bool = False
if (
rent_chan is not None
and
rent_chan.connected()
):
pchan_raddr: Address|None = rent_chan.raddr
if pchan_raddr is not None:
reg_addr: Address
for reg_addr in actor.reg_addrs:
if (
pchan_raddr.unwrap()
==
tuple(reg_addr)
):
parent_is_reg = True
break
for addr in actor.reg_addrs: for addr in actor.reg_addrs:
waddr = wrap_address(addr) waddr = wrap_address(addr)
assert waddr.is_valid assert waddr.is_valid
with trio.move_on_after(0.5) as cs: with trio.move_on_after(0.5) as cs:
cs.shield = True cs.shield = True
try: try:
if parent_is_reg:
reg_portal = Portal(rent_chan)
await reg_portal.run_from_ns(
'self',
'unregister_actor',
uid=actor.aid.uid,
)
else:
async with get_registry( async with get_registry(
addr, addr,
) as reg_portal: ) as reg_portal:
@ -1861,11 +1894,12 @@ async def async_main(
uid=actor.aid.uid, uid=actor.aid.uid,
) )
except OSError: except OSError:
failed = True failed_unreg = True
if cs.cancelled_caught:
failed = True
if failed: if cs.cancelled_caught:
failed_unreg = True
if failed_unreg:
teardown_report += ( teardown_report += (
f'-> Failed to unregister {actor.name} from ' f'-> Failed to unregister {actor.name} from '
f'registar @ {addr}\n' f'registar @ {addr}\n'