Skip to content

feat(chapel): L2.3 cancel-token preemption#154

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/chapel-l23-cancel-token
May 30, 2026
Merged

feat(chapel): L2.3 cancel-token preemption#154
hyperpolymath merged 1 commit into
mainfrom
feat/chapel-l23-cancel-token

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

@hyperpolymath hyperpolymath commented May 30, 2026

Summary

Wave-2 follow-on to PR #146. Closes the explicitly-deferred "kill
in-flight losers" gap from L2.2: once the CAS-winner is selected,
every still-polling loser observes the shared `cancelToken.cancelled`
flag on its next poll tick and SIGKILLs its own subprocess instead of
running to its per-prover timeout.

After this PR, loser wall is bounded by `pollInterval ≈ 100 ms`
rather than `max(losers)`.

What changed

  • `parallel_proof_search.chpl`

    • New `class CancelToken { var cancelled: atomic bool }` — class
      (not record) so all `coforall` tasks share by reference.
    • `tryProver` signature gains `cancelToken: borrowed CancelToken? = nil`.
      Sequential / best-of callers pass nil and behave identically.
    • tryProver's poll loop checks `cancelToken!.cancelled.read()`
      each tick; on observing true, SIGKILL → preempted result with
      `exitCode = -5` (distinct from -3 timeout / -4 subprocess error).
    • `parallelProofSearchSpeculative` creates the token and pairs
      `winnerIdx.compareAndSwap` with `cancelToken.cancelled.write(true)`
      so only the prover that wins the CAS triggers the signal.
  • `proofs/agda/ParallelSoundness.agda`

    • Header docstring extended to spell out that the existing
      `cancellation-safety` theorem IS the L2.3 preemption claim.
      No new lemma needed — `speculative (true ∷ bs) = true` for
      arbitrary `bs` is exactly what preemption preserves.
  • ADR at `docs/decisions/2026-05-30-chapel-l23-cancel-token.md`
    covering rationale, soundness, three race-condition counter-arguments,
    expected speedup, reproduction recipe, Wave-3 follow-ups.

  • Cross-link from the rehab ADR's Wave-2 plan to the new ADR.

Test plan

  • `chpl --library --static parallel_proof_search.chpl chapel_ffi_exports.chpl -I ../zig_ffi` compiles cleanly
  • `agda --safe ParallelSoundness.agda` green
  • `just bench-chapel-mrr` still returns correct speculative winners
  • Real-corpus bench showing speculative << bestof (Wave-3; trivial fixtures don't exercise enough)
  • CI: chapel-build + chapel-smoke remain green

🤖 Generated with Claude Code

…s self-SIGKILL on CAS win

Wave-2 follow-on to PR #146. Closes the explicitly-deferred "kill
in-flight losers" gap from L2.2: once the CAS-winner is selected,
every still-polling loser observes the shared `cancelToken.cancelled`
flag on its next poll tick and SIGKILLs its own subprocess instead of
running to its per-prover timeout. Loser wall is now bounded by
`pollInterval ≈ 100 ms` rather than `max(losers)`.

Changes:
- `parallel_proof_search.chpl`:
  - New `class CancelToken { var cancelled: atomic bool }` —
    class (not record) so that all `coforall` tasks share the
    same instance by reference.
  - `tryProver` signature gains `cancelToken: borrowed CancelToken? = nil`.
    Existing callers (sequential, best-of) pass nil and behave
    identically.
  - tryProver's poll loop now checks `cancelToken!.cancelled.read()`
    each tick; on observing true, SIGKILLs the subprocess and
    returns a preempted `ProofResult` with `exitCode = -5`
    (distinct from -3 timeout / -4 subprocess error).
  - `parallelProofSearchSpeculative` creates `new owned CancelToken()`
    and pairs the successful `winnerIdx.compareAndSwap` with
    `cancelToken.cancelled.write(true)` so only the SAME prover
    that wins the CAS triggers the signal (no double-write).

- `proofs/agda/ParallelSoundness.agda`:
  - Header docstring extended to spell out that the existing
    `cancellation-safety` theorem IS the L2.3 preemption claim:
    once a head witness is true, the verdict is true regardless
    of the tail. The L2.3 code change preserves this — preempted
    losers land in the result table with success=false but are
    never returned because winnerIdx is set before any
    cancellation could race the CAS.
  - No new Agda lemma — the existing theorem already covers L2.3.

- `docs/decisions/2026-05-30-chapel-l23-cancel-token.md`:
  - ADR addendum to chapel-rehabilitation.md covering the decision
    rationale, the soundness argument, three race-condition
    counter-arguments, expected speedup, reproduction recipe, and
    Wave-3 follow-ups (real-corpus bench, preemption telemetry,
    reason-string on the token).

- Cross-link from rehab ADR's Wave-2 plan to the new ADR.

Verification: `chpl --library --static -o /tmp/lib_test parallel_proof_search.chpl chapel_ffi_exports.chpl -I ../zig_ffi` compiles cleanly. `just bench-chapel-mrr` still returns correct speculative winners; the trivial fixtures don't exercise the new code path enough to show a wall-clock improvement (the bench writeup predicted this — real corpus is Wave-3).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath hyperpolymath enabled auto-merge (squash) May 30, 2026 20:47
@hyperpolymath hyperpolymath merged commit 870a2ec into main May 30, 2026
32 of 40 checks passed
@hyperpolymath hyperpolymath deleted the feat/chapel-l23-cancel-token branch May 30, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant