tractor/tractor/spawn
Gud Boi e645d3ab95 Fix subint destroy race via dedicated OS thread
`trio.to_thread.run_sync(_interpreters.exec, ...)` runs `exec()` on
a cached worker thread — and when that thread is returned to the
cache after the subint's `trio.run()` exits, CPython still keeps
the subint's tstate attached to the (now idle) worker. Result: the
teardown `_interpreters.destroy(interp_id)` in the `finally` block
can block the parent's trio loop indefinitely, waiting for a tstate
release that only happens when the worker either picks up a new job
or exits.

Manifested as intermittent mid-suite hangs under
`--spawn-backend=subint` — caught by a
`faulthandler.dump_traceback_later()` showing the main thread stuck
in `_interpreters.destroy()` at `_subint.py:293` with only an idle
trio-cache worker as the other live thread.

Deats,
- drive the subint on a plain `threading.Thread` (not
  `trio.to_thread`) so the OS thread truly exits after
  `_interpreters.exec()` returns, releasing tstate and unblocking
  destroy
- signal `subint_exited.set()` back to the parent trio loop from
  the driver thread via `trio.from_thread.run_sync(...,
  trio_token=...)` — capture the token at `subint_proc` entry
- swallow `trio.RunFinishedError` in that signal path for the case
  where parent trio has already exited (proc teardown)
- in the teardown `finally`, off-load the sync
  `driver_thread.join()` to `trio.to_thread.run_sync` (cache thread
  w/ no subint tstate → safe) so we actually wait for the driver to
  exit before `_interpreters.destroy()`

(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 31cbd11a5b)
2026-06-24 19:54:25 -04:00
..
__init__.py Restore fn-arg `_runtime_vars` in `trio_proc` teardown 2026-04-23 18:30:11 -04:00
_entry.py Tidy `spawn/` subpkg docstrings and imports 2026-04-17 19:03:00 -04:00
_forkserver_override.py Mv core mods to `runtime/`, `spawn/`, `discovery/` subpkgs 2026-04-02 17:59:13 -04:00
_mp.py Tidy `spawn/` subpkg docstrings and imports 2026-04-17 19:03:00 -04:00
_mp_fixup_main.py Fix typos + typing in `_mp_fixup_main` 2026-04-10 20:58:54 -04:00
_reap.py Add `tractor.spawn._reap.unlink_uds_bind_addrs()` 2026-06-17 17:39:44 -04:00
_spawn.py Doc the `_interpreters` private-API choice in `_subint` 2026-06-24 19:54:25 -04:00
_subint.py Fix subint destroy race via dedicated OS thread 2026-06-24 19:54:25 -04:00
_trio.py Add `tractor.spawn._reap.unlink_uds_bind_addrs()` 2026-06-17 17:39:44 -04:00