Compare commits

...

2 Commits

Author SHA1 Message Date
Gud Boi b6184ab74e Uniquify no-runtime UDS `get_random()` paths
W/o a live runtime `get_random()` named UDS socks purely by
`(prefix, pid)`, so two calls in one proc returned the SAME
`no_runtime_*@{pid}.sock` — the 2nd `.bind()` then tripped
`EADDRINUSE`. Append a per-call `uuid4().hex[:6]` token so
each call yields a distinct sockpath.

This fixes the 3 `tests.discovery.test_tpt_bind_addrs` uds
failures (one registrar + disjoint-bind, two non-registrar
binds) where `reg_addr` and a "random" bind addr aliased —
the uds CI job's only red, surfaced when this branch rebased
onto the newer base that carries those tests.

Scoped to the no-runtime branch ON PURPOSE: the runtime
`{name}@{pid}` convention stays deterministic so
`spawn._reap.unlink_uds_bind_addrs()` can still reconstruct
+ unlink a SIGKILL'd subactor's sock (#454).

Deats,
- `_uds.py`: add `uuid4` import + token in the no-runtime
  branch
- `_testing.addr`: tighten `get_rando_addr()` docstring re the
  intra-proc per-call token (not just pid-keyed namespacing)

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-06-29 17:22:41 -04:00
Gud Boi f61ed0e102 Fix `_burn` bigint blowup, ctx-mgr `_read_mhz`
Both `_burn()` impls (the `cpu-perf-check` script + the
`_measure_sustained_headroom()` probe in `tests.conftest`) grew `x`
~x**2 per iter, so the loop quickly went bigint alloc/mul-bound — a
noisy CPU load + needless memory across N procs. Mask each step to
64-bit for a steady, fixed-width ALU burn (still pegs every core,
which is all the freq probe needs).

Also, `_read_mhz()` opened the sysfs freq files without a ctx-mgr;
`with open(...)` so the FD closes deterministically (matches the
script's own `_read()`).

Review: PR #468 (Copilot)
https://github.com/goodboy/tractor/pull/468

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-06-29 17:00:53 -04:00
4 changed files with 31 additions and 7 deletions

View File

@ -77,9 +77,13 @@ def _pkg_max_mhz() -> int:
def _burn(stop: float) -> None:
# fixed-width (64-bit-masked) arithmetic keeps this a steady
# ALU load; an unmasked `x` grows ~x**2/iter into a huge bigint,
# degenerating into noisy alloc/mul-bound work (and needless
# memory) across N procs.
x: int = 1
while time.perf_counter() < stop:
x += x * x ^ 0x5
x = (x + (x * x ^ 0x5)) & 0xFFFF_FFFF_FFFF_FFFF
def main(

View File

@ -171,7 +171,8 @@ def _measure_sustained_headroom(
def _read_mhz(path: str) -> int|None:
try:
return int(open(path).read()) // 1000
with open(path) as f:
return int(f.read()) // 1000
except OSError:
return None
@ -187,9 +188,13 @@ def _measure_sustained_headroom(
return 1.
def _burn(stop: float) -> None:
# fixed-width (64-bit-masked) arithmetic keeps this a
# steady ALU load; an unmasked `x` grows ~x**2/iter into
# a huge bigint, degenerating into noisy alloc/mul-bound
# work (and needless memory) across N procs.
x: int = 1
while time.perf_counter() < stop:
x += x * x ^ 0x5
x = (x + (x * x ^ 0x5)) & 0xFFFF_FFFF_FFFF_FFFF
# explicit `fork` ctx so we're immune to whatever global
# mp start-method tractor/the suite may have set (`spawn`

View File

@ -50,9 +50,14 @@ def get_rando_addr(
fight over the bind, cascading into a chain of
"Address already in use" failures.
For UDS this concern doesn't apply: `UDSAddress.get_random()`
already builds socket paths from `os.getpid()` so each
pytest process gets its own socket-path namespace.
For UDS the *cross*-process concern is handled by keying
socket paths off `os.getpid()` (each pytest process gets its
own namespace). *Within* a process where `get_random()` has
no live runtime to name from it also appends a per-call
`uuid4` token, so two calls (e.g. a `reg_addr` + a distinct
bind addr in one test body) yield distinct sockpaths rather
than aliasing to the same `name@pid.sock` and tripping
`EADDRINUSE`.
'''
addr_type: Type[_addr.Addres] = _addr._address_types[tpt_proto]

View File

@ -36,6 +36,7 @@ from typing import (
TYPE_CHECKING,
ClassVar,
)
from uuid import uuid4
import msgspec
import trio
@ -204,7 +205,16 @@ class UDSAddress(
else:
prefix: str = 'no_runtime_actor'
sockname: str = f'{prefix}@{pid}'
# XXX, no live actor -> no `Aid` to key off, so append a
# per-CALL token: w/o a runtime the sockname is otherwise
# a pure fn of `(prefix, pid)`, so two `get_random()`
# calls in one proc alias to the SAME sockpath and the
# 2nd `.bind()` trips `EADDRINUSE`. The token makes each
# call a distinct file. Safe vs `._reap` cleanup which
# only reconstructs the runtime `{name}@{pid}` convention
# (above), never these `no_runtime_*` socks.
token: str = uuid4().hex[:6]
sockname: str = f'{prefix}@{pid}.{token}'
sockpath: Path = Path(f'{sockname}.sock')
return UDSAddress(