tractor/tractor
Gud Boi e39675f454 Add WIP `subint_fork_proc` backend scaffold
Experimental third spawn backend: use a fresh
sub-interpreter purely as a trio-free launchpad from
which to `os.fork()` + exec back into
`python -m tractor._child`. Per issue #379's
"fork()-workaround/hacks" thread.

Intent is to sidestep both,
- the trio+fork hazards hitting `trio_proc` (python- trio/trio#1614 et
  al.), since the forking interp is guaranteed trio-free.

- the shared-GIL abandoned-thread hazards hitting `subint_proc`
  (`ai/conc-anal/subint_sigint_starvation_issue.md`), since we don't
  *stay* in the subint — it only lives long enough to call `os.fork()`

Downstream of the fork+exec, all the existing `trio_proc` plumbing is
reused verbatim: `ipc_server.wait_for_peer()`, `SpawnSpec`, `Portal`
yield, soft-kill.

Status: NOT wired up beyond scaffolding. The fn raises
`NotImplementedError` immediately; the `bootstrap` fork/exec string
builder and the `# TODO: orchestrate driver thread` block are kept
in-tree as deliberate dead code so the next iteration starts from
a concrete shape rather than a blank page.

Docstring calls out three open questions that need
empirical validation before wiring this up:
1. Does CPython permit `os.fork()` from a non-main
   legacy subint?
2. Can the child stay fork-without-exec and
   `trio.run()` directly from within the launchpad
   subint?
3. How do `signal.set_wakeup_fd()` handlers and other
   process-global state interact when the forking
   thread is inside a subint?

(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 eee79a0357)
2026-06-24 18:19:16 -04:00
..
_testing Fix `add_log_level()` re-registration value drift 2026-06-24 18:03:28 -04:00
devx Hoist proc-title prefix to `_def_prefix` const 2026-06-24 16:20:50 -04:00
discovery Fix misc bugs caught by Copilot review 2026-04-14 19:54:15 -04:00
experimental Mv core mods to `runtime/`, `spawn/`, `discovery/` subpkgs 2026-04-02 17:59:13 -04:00
ipc Use `is not None` check for peer-connect `event` 2026-06-24 18:19:16 -04:00
msg Mv core mods to `runtime/`, `spawn/`, `discovery/` subpkgs 2026-04-02 17:59:13 -04:00
runtime Code-style, couple newline/ws tweaks 2026-06-24 16:20:50 -04:00
spawn Add WIP `subint_fork_proc` backend scaffold 2026-06-24 18:19:16 -04:00
trionics Add `supervise_run_process` to `trionics._subproc` 2026-06-24 18:19:16 -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 Mv core mods to `runtime/`, `spawn/`, `discovery/` subpkgs 2026-04-02 17:59:13 -04:00
_exceptions.py Add `ActorTooSlowError` for cancel-cascade timeouts 2026-06-17 17:39:44 -04:00
_root.py Code-style, couple newline/ws tweaks 2026-06-24 16:20:50 -04:00
_streaming.py Mv core mods to `runtime/`, `spawn/`, `discovery/` subpkgs 2026-04-02 17:59:13 -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