From 2de0c9bcf83763f9d76eb01828d9e178f515700c Mon Sep 17 00:00:00 2001 From: goodboy Date: Wed, 13 May 2026 10:10:27 -0400 Subject: [PATCH] Add `main_thread_forkserver` CI matrix rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `capture` dimension to CI matrix so fork-based backends run `--capture=sys` (fork-child × `--capture=fd` is a known deadlock). Non-fork backends keep `fd`. Deats, - two `include:` rows for `main_thread_forkserver` on linux py3.13: tcp + uds, both `capture: 'sys'` - job name updated to show `capture=` mode - timeout bumped 16 -> 20 min to accommodate the additional matrix cells - `--capture=${{ matrix.capture }}` replaces hardcoded `--capture=fd` (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 a24600f1a7431efbdb185ccb4abcb7c303d04a90) --- .github/workflows/ci.yml | 47 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8bb1297c..5db1c5ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,10 +88,27 @@ jobs: testing: - name: '${{ matrix.os }} Python${{ matrix.python-version }} spawn_backend=${{ matrix.spawn_backend }} tpt_proto=${{ matrix.tpt_proto }}' - timeout-minutes: 16 + name: '${{ matrix.os }} Python${{ matrix.python-version }} spawn_backend=${{ matrix.spawn_backend }} tpt_proto=${{ matrix.tpt_proto }} capture=${{ matrix.capture }}' + timeout-minutes: 20 runs-on: ${{ matrix.os }} + # NOTE on the matrix shape — the `capture=` mode follows + # `spawn_backend`: + # + # - `trio` / `mp_*` backends use `--capture=fd` (default) + # for per-test attribution of subactor *raw-fd* output + # in failure reports. + # - Fork-based backends (`main_thread_forkserver`, + # `subint_forkserver`) REQUIRE `--capture=sys` because + # fork-child × `--capture=fd` is a known deadlock + # pattern. See the long NOTE in `tractor._testing.pytest`'s + # `pytest_load_initial_conftests` for the mechanism + + # tradeoff write-up. + # + # If a future matrix row adds a fork-spawn backend + # WITHOUT setting `capture: 'sys'`, the + # `pytest_load_initial_conftests` hook fail-fasts on `CI=1` + # with a clear error msg. So the matrix is self-policing. strategy: fail-fast: false matrix: @@ -118,6 +135,26 @@ jobs: 'tcp', 'uds', ] + capture: [ + 'fd', # default for non-fork backends + ] + + # Fork-based backends — added via `include:` so each + # cell carries its REQUIRED `capture: 'sys'` mode. + # Linux-only for now; macOS coverage TBD pending + # local validation. + include: + - os: ubuntu-latest + python-version: '3.13' + spawn_backend: 'main_thread_forkserver' + tpt_proto: 'tcp' + capture: 'sys' + - os: ubuntu-latest + python-version: '3.13' + spawn_backend: 'main_thread_forkserver' + tpt_proto: 'uds' + capture: 'sys' + # https://github.com/orgs/community/discussions/26253#discussioncomment-3250989 exclude: # don't do UDS run on macOS (for now) @@ -158,7 +195,11 @@ jobs: -rsx --spawn-backend=${{ matrix.spawn_backend }} --tpt-proto=${{ matrix.tpt_proto }} - --capture=fd + --capture=${{ matrix.capture }} + # NOTE: capture mode is matrix-driven — `fd` for + # non-fork backends (per-test fd attribution), + # `sys` for fork-based (avoids fork-child x + # capture-fd deadlock). See matrix-NOTE above. # XXX legacy NOTE XXX #