From a17d87a4bd4f16c220e2d032122d8ad14e27dc79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20T=C3=B6rcsv=C3=A1ri?= Date: Wed, 5 Aug 2026 17:28:07 +0200 Subject: [PATCH] mailbox S5: scheduler is the default build + demolition ledger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injector defaults to asyncify-scheduler.js (WX_SCHEDULER=0 = explicit legacy opt-out); .ci-cache-epoch 9->10. Doc 17 S5 corrected: the interlock/busy-gate deletions assumed handler-fibers that S1-S4 never built — they stay as load-bearing second lines; each real deletion is ledgered with its unlock condition. Flip gate: full kicad suite 136 passed on BOTH variants (occ-probe glb fails identically on both = pre-existing; ngspice bg_run = rerun-passes flake). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01TfxKn5utcntBSnxz4ZnYKs --- .ci-cache-epoch | 2 +- .../async/17-mailbox-scheduler-plan.md | 30 +++++++++++++++++++ scripts/common/inject-dyncall-shims.sh | 23 ++++++++------ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/.ci-cache-epoch b/.ci-cache-epoch index ec63514..f599e28 100644 --- a/.ci-cache-epoch +++ b/.ci-cache-epoch @@ -1 +1 @@ -9 +10 diff --git a/docs/features/async/17-mailbox-scheduler-plan.md b/docs/features/async/17-mailbox-scheduler-plan.md index f1c49a8..dbb3471 100644 --- a/docs/features/async/17-mailbox-scheduler-plan.md +++ b/docs/features/async/17-mailbox-scheduler-plan.md @@ -258,6 +258,36 @@ rollback = the `WX_SCHEDULER=0` build + a per-step tag. enumerate gates. Downgrade libcontext refusals to dev-build assertions; keep counters-only beacons. Retire §3c leftovers. **Gate:** net green with `WX_SCHEDULER=1` as the only build; a full-suite run shows zero references to deleted diagnostics. + > **Work log 2026-08-05 — S5 executed as DEFAULT-FLIP + LEDGER, with a correction.** + > This step's original demolition list over-promised relative to what S1–S4 built: the + > §3b fate table assumed handler-fibers ("serialization is the scheduler's job"), but + > parks still suspend ordinary dispatch chains in place — so the **dispatch interlock, + > the ProcessEvents parked gate, the zeroed-interlock windows around waits, and the C++ + > open/fiber-busy gates remain LOAD-BEARING second lines**, not dead weight. Deleting + > them now would reopen the fp-selector trap class. What S5 delivered instead: + > **WX_SCHEDULER=1 is the DEFAULT build** (injector flip; `WX_SCHEDULER=0` = explicit + > legacy opt-out; `.ci-cache-epoch` 9→10), gated on the FULL kicad-firefox suite against + > the scheduler build, not just the trio. + > **Flip gate result:** full suite 136 passed on BOTH variants (an accidental legacy run + > — `setup:kicad` re-syncs `output/` over staged glue, converter beware — gave the + > fallback a free full net). Scheduler run: 30 skips (N2 runs there), 2 fails triaged: + > `ngspice-probe` bg_run = rerun-passes flake; `occ-probe` glb = fails IDENTICALLY on + > legacy → pre-existing local occ_service issue, tracked outside this plan. + > + > **Demolition ledger — each deletion with its unlock condition:** + > 1. Legacy opt-out + `handlesleep.js` + C++ legacy paths (`startModal`, + > `wxWasmRunNestedLoop`, popup pump, `_wxModalResolvers`/`_wxNestedLoopExit`, + > `emscripten_async_call` timer entry, timer 17 ms retry branch, `s_wxRunDepth` tick + > gate): delete TOGETHER, after CI runs scheduler-only across the full matrix + > (3 engines × both EH). They're compiled once for both variants — no partial delete. + > 2. Dispatch interlock + Paint-only gate + zero/restore windows: delete only when + > parkable handlers run on scheduler-owned fiber contexts (the remaining Design-B + > step this plan never scoped). Until then they are the mutual-exclusion story. + > 3. C++ `pcbjam_open::busy()` / `kicadCollabFiberBusy` gates: keep as second line under + > the JS embind lane; revisit only with (2). + > 4. libcontext refusals: KEEP ACTIVE (not downgraded) — `jump-refused-parked` fires + > BEFORE the doomed unwind write, the one place prevention works (doc 16); the JS + > consume-once layer is the backstop, not a replacement. - **S6 · Lifetime (few d).** Cleanup ordering vs the scheduler; teardown deferred to unload/explicit exit; `ScheduleExit` → scheduler wake (12 §phase-4). diff --git a/scripts/common/inject-dyncall-shims.sh b/scripts/common/inject-dyncall-shims.sh index 7a26e76..9799a54 100755 --- a/scripts/common/inject-dyncall-shims.sh +++ b/scripts/common/inject-dyncall-shims.sh @@ -5,8 +5,9 @@ # The actual JavaScript that gets injected lives in readable, standalone files in # scripts/common/shims/ (not inline heredocs): # - handlesleep.js nested-Asyncify handleSleep currData save/restore (#9153) -# - asyncify-scheduler.js WX_SCHEDULER=1 builds only: the mailbox/scheduler -# (docs/features/async/17; S0 = observation-only skeleton) +# - asyncify-scheduler.js the mailbox/scheduler (docs/features/async/17) — +# the DEFAULT shim; WX_SCHEDULER=0 opts back into +# the legacy handlesleep.js # - diagnostics.js optional logging-only instrumentation (see SHIM_DIAGNOSTICS) # # Native wasm-EH is the only build mode, so the .js has no invoke_* wrappers / dynCall_ call @@ -19,7 +20,7 @@ # Usage: # inject-dyncall-shims.sh # SHIM_DIAGNOSTICS=1 inject-dyncall-shims.sh # also inject diagnostics.js -# WX_SCHEDULER=1 inject-dyncall-shims.sh # also inject the scheduler (dual-glue variant) +# WX_SCHEDULER=0 inject-dyncall-shims.sh # legacy opt-out (handlesleep.js instead of the scheduler) set -e @@ -78,10 +79,14 @@ echo "Total: Fixed $TOTAL_FIXED empty callback(s)" # without it a rewind resuming through a fresh wasm re-entry hits # _asyncify_start_rewind(null) -> "memory access out of bounds"). # -# WX_SCHEDULER=1 (doc 17 S2): asyncify-scheduler.js REPLACES handlesleep.js — it -# subsumes the capture/restore, fiber guard, and trampoline heal, and adds the -# deferred-wake drain + N1 single-writer tripwire. Injecting BOTH would -# double-manage the wake path (the scheduler refuses to install its core then). +# WX_SCHEDULER (doc 17 S5): the scheduler is the DEFAULT since 2026-08-05 — +# asyncify-scheduler.js REPLACES handlesleep.js. It subsumes the +# capture/restore, fiber guard, and trampoline heal, and adds the deferred-wake +# drain + N1 single-writer tripwire + the mailbox/wait lanes. Injecting BOTH +# would double-manage the wake path (the scheduler refuses to install its core +# then). WX_SCHEDULER=0 is the explicit legacy opt-out (kept until CI has run +# scheduler-only across the full matrix; the C++ legacy paths it exercises are +# deleted together with it — see doc 17 S5's demolition ledger). # # SHIM_DISABLE_HANDLESLEEP=1 skips the legacy shim: the asyncify-races red-green # harness uses it to keep the historical "sleep buffer clobbered by fiber swap" @@ -105,13 +110,13 @@ inject_shim_at_marker() { #