From a6591050475435ab075867a1efa85adf56c79945 Mon Sep 17 00:00:00 2001 From: Peefy Date: Mon, 19 Oct 2026 20:09:24 +0800 Subject: [PATCH] fix(ci): stop the Dart suite racing the runtime's global panic hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dart-test's macos-15-intel leg failed on "plugins reports an unknown method as a KCL error rather than crashing": errMessage came back as an empty EvaluationError while the real text ("invalid method: ... is not found") went to stderr from the runtime's panic hook. The plugin agent reports a missing method the way every other KCL failure is reported — as a __kcl_PanicInfo__ object the runtime turns into a panic — and that panic's payload is captured by a process-global std::panic hook that the runtime installs and restores around every evaluation, recording into a thread-local. `dart test` runs test files in parallel isolates sharing one libkcl, so an overlapping evaluation restores the hook another thread is running under; the panicking thread then reads an empty record and the KCL error loses its message. Only the first panic on a thread shows it, which is why the next plugin test passed. Run the suite serially (~0.1s on this package) and document why in the README. The upstream fix belongs in kcl-lang/kcl, where FastRunner::run should fall back to the caught panic payload instead of unwrap_or_default(). Also drop the duplicated windows-latest matrix entry, which ran the Windows leg twice. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/dart-test.yaml | 1 - dart/README.md | 5 ++++- dart/dart_test.yaml | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 dart/dart_test.yaml diff --git a/.github/workflows/dart-test.yaml b/.github/workflows/dart-test.yaml index ecfc6a93..63b3ed55 100644 --- a/.github/workflows/dart-test.yaml +++ b/.github/workflows/dart-test.yaml @@ -49,7 +49,6 @@ jobs: - ubuntu-22.04-arm # linux-arm64 - macos-latest # darwin-arm64 - macos-15-intel # darwin-amd64 - - windows-latest # windows-amd64 # windows-11-arm is out until kcl-lang/kcl publishes a # kcl-lib--windows-arm64.zip: kcl-lang/kcl#2219 adds the # target to that repo's release matrix, but no released version has diff --git a/dart/README.md b/dart/README.md index 34f7cb06..c774dba0 100644 --- a/dart/README.md +++ b/dart/README.md @@ -125,7 +125,10 @@ try { ``` `exec_program` and `validate_code` are **not thread-safe**, mirroring the -spec. +spec. Call them from a single isolate: the shared runtime keeps process-global +state, and overlapping calls can lose a panic payload — the KCL error then +comes back with an empty message. The test suite runs one file at a time for +the same reason; see [`dart_test.yaml`](dart_test.yaml). ## API reference diff --git a/dart/dart_test.yaml b/dart/dart_test.yaml new file mode 100644 index 00000000..512ac536 --- /dev/null +++ b/dart/dart_test.yaml @@ -0,0 +1,17 @@ +# Run one test file at a time. +# +# `dart test` normally loads and runs test *files* concurrently, each in its +# own isolate — but every isolate shares the one loaded `libkcl`, and the KCL +# runtime keeps process-global state its own C API declares not thread-safe. +# The sharpest edge is the panic hook: the Rust side takes, replaces and +# restores the *process-global* `std::panic` hook around every evaluation +# (`FastRunner::run` in kcl_runner) and records the panic payload into a +# thread-local. Two overlapping evaluations can clobber each other's hook, so +# the panicking thread's payload never reaches its own record and the KCL error +# comes back with an empty message — the plugin tests in kcl_lib_test.dart +# then fail on `expect(errMessage, contains(...))`, with the real text showing +# up only in the runtime's stderr. +# +# Serial execution costs ~0.1s on this package, so the suite stays honest +# about what it exercises instead of racing the runtime. +concurrency: 1