Skip to content

Make native interop cancellation stress gate independent of runner timing #78

Description

@wieslawsoltes

Problem

The native runtime package gate runs native-interop-race --batches 100 --width 32 to verify cancellation, result-pool cleanup, and generated interop accounting across four V8 contexts. On a contended macOS hosted runner, the probe rejected otherwise valid calls with:

Generated native interop invocation was rejected: Native interop invocation queue is full

Observed failure on run 34961173025:

  • 12,800 intended operations
  • 12,672 generated calls
  • 12,672 cancellations
  • 128 queue-full faults
  • all four result/operation pools drained to zero afterward

The native engine, 21 CTests, 150-document/514-subtest required web-platform subset, media profiles, and 55 Avalonia tests had already passed. The failure was in the stress harness pacing.

Root cause

After disposing each batch's managed invokers, the probe slept for a fixed 20 ms and enqueued native-interop-race-barrier.js. TryExecuteScript only accepts that script asynchronously; it does not wait for execution. On a slower runner, cancelled promise work could remain ahead of the barrier, so multiple batches accumulated in the bounded 64-entry native interop queue.

The initial fixture installation had the same asynchronous assumption.

Fix

Draft PR #76 at consolidated commit 41cf43cc34355f9511df94631f49baa87ff8818f uses EngineMetrics.ExecutedScripts as a completion fence:

  1. Read the current counter.
  2. Enqueue the fixture or barrier script.
  3. Poll until ExecutedScripts advances, with a five-second deadline.
  4. Start the next batch only after the barrier queued behind the prior interop work has executed.

This preserves the full 100 x 32 x 4 stress workload and the queue bound. It removes wall-clock timing as a correctness condition and still fails on a real worker stall, lost script, interop fault, accounting mismatch, or leaked result/operation slot.

Validation

The benchmark project builds with zero warnings and errors. The complete PR #76 matrix passed:

  • hosted macOS, Ubuntu, and Windows builds
  • NativeAOT contracts and Linux native contracts
  • packaged Linux x64, macOS arm64, and Windows x64 runtimes
  • cross-RID candidate and required evidence
  • release-package verification
  • installed-package consumers on all three RIDs

The NuGet publish and release-commit guard were skipped by design because this is a draft, non-release revision.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions