tractor/tractor
Gud Boi 8bf8bea860 Lift fork prims into `_subint_forkserver` mod
The smoketest (prior commit) empirically validated the
"fork-from-main-interp-worker-thread" arch on py3.14. Promote
the validated primitives out of the `ai/conc-anal/` smoketest
into `tractor.spawn._subint_forkserver` so they can eventually
be wired into a real "subint forkserver" spawn backend.

Deats,
- new module `tractor/spawn/_subint_forkserver.py` (337 LOC):
  - `fork_from_worker_thread(child_target, thread_name)` —
    spawn a main-interp `threading.Thread`, call `os.fork()`
    from it, shuttle the child pid back to main via a pipe
  - `run_trio_in_subint(bootstrap, ...)` — post-fork helper:
    create a fresh subint + drive `_interpreters.exec()` on
    a dedicated worker thread running the `bootstrap` str
    (typically imports `trio`, defines an async entry, calls
    `trio.run()`)
  - `wait_child(pid, expect_exit_ok)` — `os.waitpid()` +
    pass/fail classification reusable from harness AND the
    eventual real spawn path
- feature-gated py3.14+ via the public
  `concurrent.interpreters` presence check; matches the gate
  in `tractor.spawn._subint`
- module docstring doc's the CPython-block context
  (cross-refs `_subint_fork` stub + the two `conc-anal/`
  docs) and status: EXPERIMENTAL, not yet registered in
  `_spawn._methods`

Also, refactor the smoketest
`ai/conc-anal/subint_fork_from_main_thread_smoketest.py` to
import the primitives from the new module rather than inline
its own copies. Keeps the smoketest and the tractor-side
impl in sync as the forkserver design evolves; the smoketest
remains a zero-`tractor`-runtime CPython-level check
(imports ONLY the three primitives, no runtime bring-up).

Status: next step is to drive these from a parent-side
`trio.run()` and hook the returned child pid into the normal
actor-nursery/IPC flow — then register `subint_forkserver`
as a `SpawnMethodKey` in `_spawn.py`.

(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 82332fbceb)
2026-06-29 19:20:21 -04:00
..
_testing Uniquify no-runtime UDS `get_random()` paths 2026-06-29 18:08:50 -04:00
devx Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
discovery Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
experimental Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
ipc Fix uds `get_random` reaper-regex break (+2 nits) 2026-06-29 18:51:26 -04:00
msg Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
runtime Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
spawn Lift fork prims into `_subint_forkserver` mod 2026-06-29 19:20:21 -04:00
trionics Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
__init__.py Rename `discovery._discovery` to `._api` 2026-04-14 19:54:14 -04:00
_child.py Add per-actor `setproctitle` via `devx._proctitle` 2026-06-17 17:39:44 -04:00
_clustering.py Use `.aid.uid` to avoid deprecation warns 2026-03-13 21:10:52 -04:00
_code_load.py Mv `load_module_from_path()` to a new `._code_load` submod 2026-02-11 21:03:29 -05:00
_context.py Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
_exceptions.py Fix informal-RST in docstrings for clean autodoc 2026-06-28 13:29:01 -04:00
_root.py Code-style, couple newline/ws tweaks 2026-06-24 16:20:50 -04:00
_streaming.py Use `aid.uid` over manual `(name, uuid)` tuples 2026-06-27 21:38:30 -04:00
log.py Fix `add_log_level()` re-registration value drift 2026-06-24 18:03:28 -04:00
to_asyncio.py Add `maybe_signal_aio_task()` + cause-chain guard 2026-06-17 17:39:44 -04:00