From 40c30940775819686475dfd485fa767fdc60a4ac Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sun, 5 Jul 2026 23:22:29 +0800 Subject: [PATCH] ci: run whole workspace single-threaded on Windows (skia/DirectWrite) The STATUS_ACCESS_VIOLATION is not confined to op-host-native/-desktop: any crate whose tests reach a skia FontMgr (DirectWrite) via NativeBackend or SkiaMeasure crashes when that test binary runs across parallel worker threads (op-host-services surfaced next). Excluding crates one-by-one doesn't converge. Instead run the entire workspace with --test-threads=1 on Windows only; each binary is serialized (cross-process concurrency is safe), covering every skia-touching crate at once. macOS / Linux stay parallel. --- .github/workflows/rust-check.yml | 22 +++++++++++++-------- .github/workflows/rust-multiplatform.yml | 25 ++++++++++++------------ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/.github/workflows/rust-check.yml b/.github/workflows/rust-check.yml index 90b8c731a..5b826a9d3 100644 --- a/.github/workflows/rust-check.yml +++ b/.github/workflows/rust-check.yml @@ -71,15 +71,21 @@ jobs: # EGL, so STEP1A_REQUIRE_GPU is left unset: the op-host-native GPU # smoke (memory_loop) self-uses the raster fallback instead of # hard-failing on EGL init. Real-GPU coverage runs on dev machines. - - run: cargo test --workspace --exclude op-host-native --exclude op-host-desktop - # op-host-native (+ op-host-desktop, which wraps it) build native - # `NativeBackend`s that create a skia `FontMgr` (DirectWrite on Windows). - # Concurrent DirectWrite init/use across cargo's parallel test-worker - # threads segfaults on the Windows runner (STATUS_ACCESS_VIOLATION), so - # serialize both crates' tests. macOS / Linux are unaffected either way. - - run: cargo test -p op-host-native -p op-host-desktop -- --test-threads=1 + # Windows runs the whole workspace single-threaded. Many crates' tests + # (op-host-native / -desktop / -services / …) trigger a skia `FontMgr` + # (DirectWrite on Windows) via NativeBackend or SkiaMeasure; concurrent + # DirectWrite init across a test binary's parallel worker threads + # segfaults (STATUS_ACCESS_VIOLATION). `--test-threads=1` serializes each + # binary — cross-binary (separate-process) concurrency is safe, so one + # flag covers every skia-touching crate. macOS / Linux run in parallel. + - name: Test workspace (non-Windows, parallel) + if: runner.os != 'Windows' + run: cargo test --workspace + - name: Test workspace (Windows, serialized — skia/DirectWrite) + if: runner.os == 'Windows' + run: cargo test --workspace -- --test-threads=1 - name: Run CanvasKit web host tests - run: cargo test -p op-host-web --features canvaskit + run: cargo test -p op-host-web --features canvaskit -- --test-threads=1 - run: cargo clippy --workspace --all-targets -- -D warnings # Step 1a Phase C Task 4: spec v19 §11 + §12.3 boundary invariants. # Linux runner has the full mobile target stdlib (`rustup target add` diff --git a/.github/workflows/rust-multiplatform.yml b/.github/workflows/rust-multiplatform.yml index 50cd03a91..f10840ff6 100644 --- a/.github/workflows/rust-multiplatform.yml +++ b/.github/workflows/rust-multiplatform.yml @@ -114,19 +114,18 @@ jobs: # EGL/Mesa stack they soft-skip (INCONCLUSIVE eprintln); set # STEP1A_REQUIRE_GPU=1 on a known-good GPU runner to fail hard. run: cargo test --workspace --target ${{ matrix.target }} - - name: Test (host, macOS / Windows) - if: matrix.cross == false && matrix.check_only != true && runner.os != 'Linux' - run: cargo test --workspace --exclude op-host-native --exclude op-host-desktop --target ${{ matrix.target }} - - name: Test skia host crates (macOS / Windows, serialized) - if: matrix.cross == false && matrix.check_only != true && runner.os != 'Linux' - # op-host-native (+ op-host-desktop) build native NativeBackends whose - # skia FontMgr (DirectWrite) segfaults across parallel test-worker - # threads on the Windows runner (STATUS_ACCESS_VIOLATION). Run - # single-threaded (matches rust-check.yml). A SEPARATE step — not a - # second line in the step above — because Windows runs multi-line - # run: blocks under PowerShell, which only fails on the LAST command's - # exit code and would mask a failure in the workspace test above. - run: cargo test -p op-host-native -p op-host-desktop --target ${{ matrix.target }} -- --test-threads=1 + - name: Test (host, macOS — parallel) + if: matrix.cross == false && matrix.check_only != true && runner.os == 'macOS' + run: cargo test --workspace --target ${{ matrix.target }} + # Windows runs the whole workspace single-threaded: many crates' tests + # trigger a skia FontMgr (DirectWrite) via NativeBackend / SkiaMeasure, + # and concurrent DirectWrite init across a test binary's parallel worker + # threads segfaults (STATUS_ACCESS_VIOLATION). --test-threads=1 serializes + # each binary; cross-binary (separate-process) concurrency is safe, so + # one flag covers every skia-touching crate. Matches rust-check.yml. + - name: Test (host, Windows — serialized skia/DirectWrite) + if: matrix.cross == false && matrix.check_only != true && runner.os == 'Windows' + run: cargo test --workspace --target ${{ matrix.target }} -- --test-threads=1 # Desktop binary artifact upload is intentionally not wired here yet. # The real desktop binary lives in the `op-host-desktop` crate; a # build + upload step can be added once release packaging is finalized.