tractor/tests
Gud Boi 7f1fa2c3a5 Wire `subint_forkserver` as first-class backend
Promote `_subint_forkserver` from primitives-only into a
registered spawn backend: `'subint_forkserver'` is now a
`SpawnMethodKey` literal, dispatched via `_methods` to
the new `subint_forkserver_proc()` target, feature-gated
under the existing `subint`-family py3.14+ case, and
selectable via `--spawn-backend=subint_forkserver`.

Deats,
- new `subint_forkserver_proc()` spawn target in
  `_subint_forkserver`:
  - mirrors `trio_proc()`'s supervision model — real OS
    subprocess so `Portal.cancel_actor()` + `soft_kill()`
    on graceful teardown, `os.kill(SIGKILL)` on hard-reap
    (no `_interpreters.destroy()` race to fuss over bc the
    child lives in its own process)
  - only real diff from `trio_proc` is the spawn mechanism:
    fork from a main-interp worker thread via
    `fork_from_worker_thread()` (off-loaded to trio's
    thread pool) instead of `trio.lowlevel.open_process()`
  - child-side `_child_target` closure runs
    `tractor._child._actor_child_main()` with
    `spawn_method='trio'` — the child is a regular trio
    actor, "subint_forkserver" names how the parent
    spawned, not what the child runs
- new `_ForkedProc` class — thin `trio.Process`-compatible
  shim around a raw OS pid: `.poll()` via
  `waitpid(WNOHANG)`, async `.wait()` off-loaded to a trio
  cache thread, `.kill()` via `SIGKILL`, `.returncode`
  cached for repeat calls. `.stdin`/`.stdout`/`.stderr`
  are `None` (fork-w/o-exec inherits parent FDs; we don't
  marshal them) which matches `soft_kill()`'s `is not None`
  guards

Also, new backend-tier test
`test_subint_forkserver_spawn_basic` drives the registered
backend end-to-end via `open_root_actor` + `open_nursery` +
`run_in_actor` w/ a trivial portal-RPC round-trip. Uses a
`forkserver_spawn_method` fixture to flip
`_spawn_method`/`_ctx` for the test's duration + restore on
teardown (so other session-level tests don't observe the
global flip). Test module docstring reworked to describe
the three tiers now covered: (1) primitive-level, (2)
parent-trio-driven primitives, (3) full registered backend.

Status: still-open work (tracked on `tractor#379`) doc'd
inline in the module docstring — no cancel/hard-kill stress
coverage yet, child-side subint-hosted root runtime still
future (gated on `msgspec#563`), thread-hygiene audit
pending the same unblock.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code

(cherry picked from commit 26914fde75)
2026-06-29 19:20:21 -04:00
..
devx Add `cpu_perf_headroom()` for throttle-aware deadlines 2026-06-29 18:08:50 -04:00
discovery Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
ipc Add `enable_transports`/`registry_addrs` proto guard 2026-06-17 17:39:44 -04:00
msg Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
spawn Wire `subint_forkserver` as first-class backend 2026-06-29 19:20:21 -04:00
trionics Skip `test_parent_tty_isolated` off-Linux (`/proc`-only) 2026-06-24 18:19:16 -04:00
__init__.py Add `tests/__init__.py` for `.conftest` imports 2025-03-20 20:53:54 -04:00
conftest.py Fix uds `get_random` reaper-regex break (+2 nits) 2026-06-29 18:51:26 -04:00
test_2way.py Tidy a typing-typo, add explicit `ids=` for paramed suites 2026-03-09 19:35:47 -04:00
test_advanced_faults.py Revert advanced-fault UDS edge case handling 2026-03-13 21:10:52 -04:00
test_advanced_streaming.py Add `cpu_perf_headroom()` for throttle-aware deadlines 2026-06-29 18:08:50 -04:00
test_cancellation.py Use `cpu_perf_headroom()` for timing-test deadlines 2026-06-29 18:08:50 -04:00
test_child_manages_service_nursery.py Swap `open_channel_from()` to yield `(chan, first)` 2026-03-13 19:28:57 -04:00
test_clustering.py Add `cpu_perf_headroom()` for throttle-aware deadlines 2026-06-29 18:08:50 -04:00
test_context_stream_semantics.py Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
test_docs_examples.py Use `cpu_perf_headroom()` at remaining deadlines 2026-06-29 18:13:47 -04:00
test_infected_asyncio.py Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
test_inter_peer_cancellation.py Use `cpu_perf_headroom()` at remaining deadlines 2026-06-29 18:13:47 -04:00
test_legacy_one_way_streaming.py Use `cpu_perf_headroom()` for timing-test deadlines 2026-06-29 18:08:50 -04:00
test_local.py Use `.aid` fields over deprecated `.uid` in tests 2026-06-25 17:44:22 -04:00
test_log_sys.py Add `add_log_level()` factory + register `IO`=21 2026-06-24 16:20:50 -04:00
test_oob_cancellation.py Woops, fix missing `assert` thanks to copilot 2025-09-11 13:13:18 -04:00
test_pubsub.py Mark `subint`-hanging tests with `skipon_spawn_backend` 2026-06-17 17:39:44 -04:00
test_reg_err_types.py Drop stale `.cancel()`, fix docstring typo in tests 2026-04-02 18:21:19 -04:00
test_remote_exc_relay.py Adjust ep-masking-suite for the real-use-case 2025-07-15 07:23:21 -04:00
test_resource_cache.py Use `cpu_perf_headroom()` at remaining deadlines 2026-06-29 18:13:47 -04:00
test_ringbuf.py Handle py3.14+ incompats as test skips 2026-06-17 17:39:44 -04:00
test_root_infect_asyncio.py Swap `open_channel_from()` to yield `(chan, first)` 2026-03-13 19:28:57 -04:00
test_root_runtime.py Update tests+examples imports for new subpkgs 2026-04-02 17:59:13 -04:00
test_rpc.py Rename `Arbiter` -> `Registrar`, mv to `discovery._registry` 2026-04-02 17:59:13 -04:00
test_runtime.py Repair lifetime-stack suite's flakiness 2026-03-13 21:10:52 -04:00
test_shm.py Sweep `subint_forkserver` → `main_thread_forkserver` in code 2026-06-17 17:39:44 -04:00
test_spawning.py Use `cpu_perf_headroom()` at remaining deadlines 2026-06-29 18:13:47 -04:00
test_subint_cancellation.py Wall-cap `subint` audit tests via `pytest-timeout` 2026-06-29 19:20:21 -04:00
test_task_broadcasting.py Tweak timeouts and rm `arbiter_addr` in tests 2026-04-14 19:54:14 -04:00
test_trioisms.py Tweaks from copilot, type fix, typos, language. 2025-09-11 10:01:25 -04:00