Skip to content

Support explicit cancellation of Wasm execution#28

Merged
chaploud merged 3 commits intoclojurewasm:mainfrom
jtakakura:feat/execution-cancellation
Apr 24, 2026
Merged

Support explicit cancellation of Wasm execution#28
chaploud merged 3 commits intoclojurewasm:mainfrom
jtakakura:feat/execution-cancellation

Conversation

@jtakakura
Copy link
Copy Markdown
Contributor

Summary

This PR implements a mechanism to explicitly cancel a running WebAssembly instance from an external thread, as requested in #27.

Previously, execution could only be stopped via pre-set fuel limits or deadline timeouts. This change introduces a thread-safe cancelled flag in the Vm struct, allowing host applications to interrupt long-running or infinite loops from a different thread.

Proposed Changes

Core VM Implementation

  • Added cancelled: std.atomic.Value(bool) to the Vm struct for thread-safe concurrent access.
  • Implemented Vm.cancel() to set the flag and ensured Vm.reset() clears it at the start of each invocation.
  • Integrated the check into consumeInstructionBudget(). This allows the VM to stop execution at the next checkpoint (~every 1024 instructions).
  • Updated the JIT execution path (jitFuelCheckHelper) to honor the cancellation flag.

Public API

  • Zig API: Added WasmModule.cancel() as a high-level method to request cancellation.
  • C API: Added zwasm_module_cancel(zwasm_module_t *module) to include/zwasm.h and src/c_api.zig.
  • Errors: Added error.Canceled and updated the CLI to provide a descriptive error message when cancellation occurs.

Testing

  • Added unit tests in src/vm.zig that simulate a background thread canceling both interpreter and JIT-compiled loops.
  • Enhanced C API tests in test/c_api/test_ffi.c to verify that the zwasm_module_cancel symbol is correctly exported and functional in a multi-threaded C environment.

Related Issue

Closes #27

@jtakakura jtakakura force-pushed the feat/execution-cancellation branch 7 times, most recently from c643a26 to d5b5615 Compare April 11, 2026 00:06
@jtakakura jtakakura force-pushed the feat/execution-cancellation branch 5 times, most recently from 3438e30 to 04e81c8 Compare April 12, 2026 03:19
chaploud added a commit that referenced this pull request Apr 15, 2026
Establishes a reference point on main (201d13c, after PRs #32/#33/#35 merged)
for comparison against upcoming changes that touch the VM hot path — notably
PR #28's cancellation checks in consumeInstructionBudget.

Delta vs previous baseline w45-simd-loop-persist (2026-03-26, 1e406db):
major speedups in realworld C benchmarks (rw_c_matrix -82%, rw_c_math -69%,
rw_cpp_sort -28%) from unrelated interim commits; sub-ms regressions on
st_ackermann and st_nestedloop are at-or-below the noise floor and not
attributable to PR #32 (its invoke() change adds three null-branch guards
with no observable cost when persistent fields are unset, which is the
bench configuration).
@jtakakura jtakakura force-pushed the feat/execution-cancellation branch from 04e81c8 to 4b07665 Compare April 21, 2026 12:13
perf: optimize atomic memory ordering in cancellation logic and add VS Code project settings
@jtakakura jtakakura force-pushed the feat/execution-cancellation branch from 4b07665 to 27579aa Compare April 22, 2026 08:02
@jtakakura jtakakura marked this pull request as ready for review April 22, 2026 08:31
@jtakakura jtakakura marked this pull request as draft April 22, 2026 08:40
@jtakakura jtakakura force-pushed the feat/execution-cancellation branch from 27579aa to aab626f Compare April 22, 2026 08:48
@jtakakura jtakakura force-pushed the feat/execution-cancellation branch from aab626f to 48b3f53 Compare April 22, 2026 09:05
@jtakakura jtakakura marked this pull request as ready for review April 22, 2026 09:35
chaploud added a commit that referenced this pull request Apr 24, 2026
…lation

Merge PR #28: Execution cancellation API (jtakakura) + refinements
@chaploud chaploud merged commit 48b3f53 into clojurewasm:main Apr 24, 2026
5 checks passed
@chaploud
Copy link
Copy Markdown
Contributor

Hi @jtakakura — thanks again for this contribution. Shipped in v1.9.0 (commit 231c7ca) via #43, which preserves your three commits verbatim as the base of the feature branch.

Refinements added on top (6 follow-up commits)

  • loadLinked signature kept stable — dropped the positional cancellable: bool to preserve source compatibility. Hosts that need the opt-out can set result.module.vm.cancellable = false after load; the docstring points at this.
  • Config.cancellable: ?bool — normalised to an optional to match the other override fields (fuel, force_interpreter, ...). The C ABI surface of zwasm_config_set_cancellable is unchanged.
  • Zig WasmModule.cancel() docstring — spelled out the reset-at-invoke race you already accounted for in the FFI test, so Zig callers see the same note the C header carries.
  • D134 in .dev/decisions.md — captures the design rationale (atomic flag on existing deadline checkpoints, JIT fuel cap, opt-out path).
  • CHANGELOG entry + bench/history.yaml PR28 baseline — long benches within ±1% of v1.8.0, confirming the default-on periodic check has no measurable impact on the hot path.

Verified

  • CI green (Ubuntu / macOS / Windows / size-matrix / benchmark).
  • Ubuntu x86_64 Merge Gate locally via OrbStack — unit 407/410, spec 62263/62263, e2e 796/796, realworld 50/50, FFI 80/80, minimal 267/282.
  • ClojureWasm downstream verification — test/run_all.sh --quick 4/4 pass against v1.9.0.

v1.9.0 is tagged and pushed. ClojureWasm bump PR: clojurewasm/ClojureWasm#3. Thanks for the patient and well-scoped work — the FFI thread-safety test in particular was a great addition. Closing this PR as merged.

@jtakakura jtakakura deleted the feat/execution-cancellation branch April 24, 2026 10:14
@jtakakura
Copy link
Copy Markdown
Contributor Author

@chaploud Thrilled to see v1.9.0 shipped ㊗️
Thanks for the refinements and for keeping my commits as the base.
I'm especially glad the FFI thread-safety tests were useful.
It’s been a great experience contributing to zwasm and I'm looking forward to using this in my own project.

pull Bot pushed a commit to DaviRain-Su/zwasm that referenced this pull request Apr 24, 2026
Captures the design behind PR clojurewasm#28: atomic flag piggybacking on the existing
deadline checkpoints, JIT fuel cap to periodically fire the helper, reset-at-
invoke semantics, and the cancellable=false opt-out for peak-throughput hosts.
pull Bot pushed a commit to DaviRain-Su/zwasm that referenced this pull request Apr 24, 2026
Document the Zig/C/CLI surface added by PR clojurewasm#28 and the default-on JIT
checkpoint behaviour so v1.9.0 release notes can be assembled from the
Unreleased block without archaeology.
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.

Support explicit cancellation of Wasm execution

2 participants