Add `enable_transports`/`registry_addrs` proto guard

Raise `ValueError` from `open_root_actor()` when any
`registry_addrs` entry uses a transport proto not in
`enable_transports` — historically this caused a
silent indefinite hang during the registrar handshake
(the actor could never connect to register/discover).

Also,
- update `test_root_passes_tpt_to_sub` to detect a
  proto mismatch between parametrized `tpt_proto_key`
  and CLI `tpt_proto`, asserting the new guard raises
  `ValueError` with expected msg content.
- replace old commented-out notes with a clearer
  explanation of the mismatch foot-gun.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
subint_forkserver_backend
Gud Boi 2026-05-06 15:13:02 -04:00
parent 7882c37ce0
commit d036ef7d7f
2 changed files with 48 additions and 7 deletions

View File

@ -59,15 +59,18 @@ async def chk_tpts(
)
def test_root_passes_tpt_to_sub(
tpt_proto_key: str,
tpt_proto: str,
reg_addr: tuple,
debug_mode: bool,
):
# XXX NOTE, the `reg_addr` addr won't be the same type as the
# `tpt_proto_key` would deliver here unless you pass `--tpt-proto
# <tpt_proto_key>` on the CLI.
#
# if tpt_proto_key == 'uds':
# breakpoint()
# `reg_addr` is sourced from the CLI `--tpt-proto={tpt_proto}`,
# so when the parametrized `tpt_proto_key` differs, the test
# asks the runtime to `enable_transports=[<other_proto>]` while
# pointing `registry_addrs` at a `reg_addr` of the wrong proto.
# The layer-2 guard in `open_root_actor` is expected to fail
# fast with `ValueError` on this mismatch (rather than the prior
# silent hang during the registrar handshake).
proto_mismatch: bool = (tpt_proto_key != tpt_proto)
async def main():
async with tractor.open_nursery(
@ -99,4 +102,14 @@ def test_root_passes_tpt_to_sub(
# shudown sub-actor(s)
await an.cancel()
if proto_mismatch:
# mismatched proto must raise `ValueError` from the
# `open_root_actor` runtime guard before any subactor spawn.
with pytest.raises(ValueError) as excinfo:
trio.run(main)
msg: str = str(excinfo.value)
assert 'enable_transports' in msg
assert 'registry_addrs' in msg
assert tpt_proto_key in msg or tpt_proto in msg
else:
trio.run(main)

View File

@ -371,6 +371,34 @@ async def open_root_actor(
for uw_addr in uw_reg_addrs
]
# fail-fast on `enable_transports` / `registry_addrs` proto
# mismatch — historically this caused a silent indefinite
# hang during the registrar handshake (registry was reachable
# only via a transport not in `enable_transports`, so the
# actor could never connect to register/discover). See
# `tests/ipc/test_multi_tpt.py::test_root_passes_tpt_to_sub`
# for the foot-gun case + its layer-1 skip-guard.
bad_addrs: list[tuple[str, Address]] = [
(addr.proto_key, addr)
for addr in registry_addrs
if addr.proto_key not in enable_transports
]
if bad_addrs:
raise ValueError(
f'`registry_addrs` contains addr(s) whose proto is '
f'not in `enable_transports`!\n'
f'enable_transports: {enable_transports!r}\n'
f'mismatched_addrs:\n'
+ '\n'.join(
f' - proto_key={pk!r} addr={a!r}'
for pk, a in bad_addrs
)
+ '\n\n'
f'Either add the missing proto to '
f'`enable_transports`, or remove the addr from '
f'`registry_addrs`.'
)
# Debug-mode is currently only supported for backends whose
# subactor root runtime is trio-native (so `tractor.devx.
# debug._tty_lock` works). See `_DEBUG_COMPATIBLE_BACKENDS`