From 3a582c9f37a6d12d6e19fa380b70168b30dec3f8 Mon Sep 17 00:00:00 2001 From: Rui Luo Date: Fri, 23 Oct 2026 14:42:26 +0800 Subject: [PATCH 1/3] ci: run coverage pytest on main thread with larger stack --- .github/workflows/coverage.yml | 2 +- ci/tools/run_pytest_with_stack.py | 97 ++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index aee89d41f2d..448e13ad2ff 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -440,7 +440,7 @@ jobs: "$GITHUB_WORKSPACE/.venv/Scripts/pytest" -v --cov=./cuda --cov-append --cov-context=test --cov-config="$GITHUB_WORKSPACE/.coveragerc" "$GITHUB_WORKSPACE/cuda_pathfinder/tests" # Cython linetrace under coverage on Windows needs more stack than the - # default 1 MB thread size. The helper runs pytest on an 8 MB thread. + # default 1 MB. The helper runs pytest on the main thread with 8 MB. - name: Run cuda.bindings tests (with 8MB stack) continue-on-error: true run: | diff --git a/ci/tools/run_pytest_with_stack.py b/ci/tools/run_pytest_with_stack.py index e1e1f782ba1..12abb49d766 100644 --- a/ci/tools/run_pytest_with_stack.py +++ b/ci/tools/run_pytest_with_stack.py @@ -4,24 +4,88 @@ # # SPDX-License-Identifier: Apache-2.0 -"""Run pytest on a thread with a larger stack size. +"""Run pytest on Python's main thread with a larger stack. -Cython linetrace instrumentation under coverage on Windows can exceed the -default 1 MB thread stack. This helper spawns a single worker thread with -a configurable stack (default 8 MB) so the rest of the CI workflow stays -readable. +On Windows, start a temporary copy of the base Python executable with an +8 MB PE stack reservation. This preserves the virtual environment without +modifying the installed executable. Running pytest on the main thread lets +CPython process pending calls used by CUDA graph cleanup. Usage: python run_pytest_with_stack.py [--stack-mb N] [--cwd DIR] [pytest args ...] """ import argparse -import concurrent.futures import os +import struct +import subprocess import sys -import threading +import tempfile +from pathlib import Path -import pytest + +def _python_with_stack(executable, stack_bytes): + """Return a PE executable image with at least the requested stack reserve.""" + image = bytearray(executable.read_bytes()) + if len(image) < 64 or image[:2] != b"MZ": + raise ValueError(f"Not a PE executable: {executable}") + pe_offset = struct.unpack_from(" Date: Fri, 23 Oct 2026 15:17:43 +0800 Subject: [PATCH 2/3] ci: keep manual PR coverage runs from deploying --- .github/workflows/coverage.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 448e13ad2ff..f0bd243f24e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -581,7 +581,11 @@ jobs: # GitHub discards prerequisite artifacts on a new run attempt. If only this # job fails, use "Re-run all jobs" so coverage recreates its payload. needs: combine-and-deploy - if: ${{ needs.combine-and-deploy.result == 'success' && github.repository_owner == 'nvidia' }} + # Manual runs on PR mirror branches should not publish over main's report. + if: >- + needs.combine-and-deploy.result == 'success' && + github.repository_owner == 'nvidia' && + github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write From 05cfa54bf111441fcae00ea7dd3f2b4af0e02645 Mon Sep 17 00:00:00 2001 From: Rui Luo Date: Tue, 3 Nov 2026 13:55:39 +0800 Subject: [PATCH 3/3] ci: fix Windows coverage test stacks --- .github/workflows/coverage.yml | 13 +++- ci/tools/run_pytest_with_stack.py | 57 ++---------------- ci/tools/set_windows_python_stack.ps1 | 85 +++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 53 deletions(-) create mode 100644 ci/tools/set_windows_python_stack.ps1 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9ffda254021..475701ff2d8 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -386,6 +386,15 @@ jobs: python-version: ${{ env.PY_VER }} venv: .venv + # This job installs a separate Python from the wheel-build job. Give its + # main thread and test subprocesses enough stack for coverage-built bindings. + - name: Raise the test interpreter's stack reserve to 8 MiB + shell: powershell + run: | + $basePy = & .venv/Scripts/python.exe -c "import sys; print(sys._base_executable)" + if ($LASTEXITCODE -ne 0) { throw "Could not locate base Python executable" } + & ./ci/tools/set_windows_python_stack.ps1 -Executable $basePy -ReserveBytes 8388608 + - name: Set up mini CTK uses: ./.github/actions/fetch_ctk continue-on-error: false @@ -435,8 +444,8 @@ jobs: cd "${{ steps.install-root.outputs.INSTALL_ROOT }}" "$GITHUB_WORKSPACE/.venv/Scripts/pytest" -v --cov=./cuda --cov-append --cov-context=test --cov-config="$GITHUB_WORKSPACE/.coveragerc" "$GITHUB_WORKSPACE/cuda_pathfinder/tests" - # Cython linetrace under coverage on Windows needs more stack than the - # default 1 MB. The helper runs pytest on the main thread with 8 MB. + # The patched interpreter gives pytest's main thread and subprocesses + # 8 MiB; the helper gives threads created during pytest the same stack. - name: Run cuda.bindings tests (with 8MB stack) continue-on-error: true run: | diff --git a/ci/tools/run_pytest_with_stack.py b/ci/tools/run_pytest_with_stack.py index 12abb49d766..a1fb2ef53ce 100644 --- a/ci/tools/run_pytest_with_stack.py +++ b/ci/tools/run_pytest_with_stack.py @@ -6,10 +6,10 @@ """Run pytest on Python's main thread with a larger stack. -On Windows, start a temporary copy of the base Python executable with an -8 MB PE stack reservation. This preserves the virtual environment without -modifying the installed executable. Running pytest on the main thread lets -CPython process pending calls used by CUDA graph cleanup. +The Windows coverage workflow first raises the base interpreter's PE stack +reserve to 8 MB, covering the main thread and test subprocesses. Set the +stack size for threads started during pytest to match. Running pytest on the +main thread lets CPython process pending calls used by CUDA graph cleanup. Usage: python run_pytest_with_stack.py [--stack-mb N] [--cwd DIR] [pytest args ...] @@ -17,50 +17,8 @@ import argparse import os -import struct -import subprocess import sys -import tempfile -from pathlib import Path - - -def _python_with_stack(executable, stack_bytes): - """Return a PE executable image with at least the requested stack reserve.""" - image = bytearray(executable.read_bytes()) - if len(image) < 64 or image[:2] != b"MZ": - raise ValueError(f"Not a PE executable: {executable}") - pe_offset = struct.unpack_from(" $actual bytes"