Skip to content

wasm-gui: a WebAssembly Linux desktop (M1–M6) rendered by the native Rust client#104

Open
NathanFlurry wants to merge 660 commits into
mainfrom
wasm-gui-desktop
Open

wasm-gui: a WebAssembly Linux desktop (M1–M6) rendered by the native Rust client#104
NathanFlurry wants to merge 660 commits into
mainfrom
wasm-gui-desktop

Conversation

@NathanFlurry

@NathanFlurry NathanFlurry commented Jun 20, 2026

Copy link
Copy Markdown
Member

Experiment under experiments/wasm-gui/: a graphical Linux desktop built by cross-compiling real, standard X11 software to wasm32-wasip1 with our own toolchain and running it inside the real secure-exec V8 sidecar, rendered by a native Rust app on crates/secure-exec-client (per SPEC §1a: no wasmer / node:wasi / TS client / Command::new in the execute+render path).

What works (all wasm guests in one VM, over host_net AF_UNIX)

  • M1–M5: the standard X.Org window manager twm decorates a real libX11 client window; multi-client compositing. Tests: test-m4b.sh, test-m5-multiclient.sh, test-m5-twm.sh.
  • M6.4 — robust multi-app desktop: twm concurrently manages a real libX11 window and a stock xclock (live analog face), past 30s, 3/3 deterministic. test-m6-desktop.sh. Proof: ~/tmp/gui-progress/m6-desktop-robust.png.
  • M6.1 (input): host-driven input via XTEST reaches a real libX11 client (ButtonPress → window repaints). test-m6-input.sh.
  • M6.2 (fonts): real X core fonts served by the server; libX11 locale DB install so Xt apps build a fontset; Xft stack cross-compiled (expat + fontconfig + libXft).

Core sidecar fixes (benefit all of secure-exec)

  • sync-RPC fairness: net.poll blocked the single service thread up to 50ms, starving other guests; lowered to 3ms so it round-robins.
  • WASM execution budget: long-running guests (the X server) were killed at the 30s default fuel budget; configurable via limits.resources.maxWasmFuel.

Notes

  • Cross-compiled from source: Xvfb, twm, xclock, libX11/libxcb/libXt/libXaw/libXft/fontconfig/freetype/pixman/… (see third_party/, scripts/).
  • The live winit window blit needs a machine with a display to verify (the dev box is headless); the input delivery path is verified headlessly via XTEST.
  • Remaining M6: xterm (needs a kernel-PTY-spawn shim + a wasm shell); then M7 (JWM), M8 (GTK DE). See experiments/wasm-gui/SPEC.md.

@railway-app

railway-app Bot commented Jun 20, 2026

Copy link
Copy Markdown

🚅 Environment secure-exec-pr-104 in rivet-frontend has no services deployed.

@NathanFlurry NathanFlurry force-pushed the wasm-gui-desktop branch 29 times, most recently from 89726df to 172f709 Compare June 21, 2026 04:41
@NathanFlurry NathanFlurry force-pushed the wasm-gui-desktop branch 16 times, most recently from 6636753 to 7a09801 Compare July 4, 2026 02:09
…sure-boot harness (RECV_OFFBROKER, RPC_BLOCK_US, DEADLINE_PROBE, POLLWAITPROF, POLL_TRACE, HOPPROF, RPC_PROFILE, TEE_GUEST_STDERR, SX_SERIAL_SETTLE_MS, SX_READY_GATE, POLL_MAX_WAIT_MS, INLINE_SOCKET_DATA)
…were launched twice (second dbusd collides on the bound socket); unblocks the concurrent launch-gate livelock (all 5 xclients launch vs 1)
…lkit (rpc-block threshold, deadline-probe, guest-stderr tee) + inline net.write scaffold (gated OFF, refuted)
…on (~96 sites) + reentrant-deadlock fixes; deadlock-free, renders 4/5 FULL at 55s (1/5 app-overlap flakiness, being characterized vs 5/5 baseline)
…cking lock for cross-thread contention + thread-local same-thread reentrancy panic) + gated SX_PARALLEL_VMS multi_thread runtime flag; prerequisites for per-session servicing tasks. No behavior change default (single-thread); SX_PARALLEL_VMS=1 boots FULL. + Increment 2 concrete design in PARALLEL-SERVICING-PLAN.md + step-0 baseline finding (Increment 1 clean, baseline also 4/5)
…ervicing + response delivery into service_hot_javascript_sync_rpc(vm, bridge, poll_waiter) free fn (one lock, no re-lock); rare arms unchanged. Behavior-preserving (3/3 FULL, 85 lib tests pass); prereq for per-VM servicing tasks
…X_PARALLEL_VMS) + VFS Send refactor + real deadlock fix

Each VM can be serviced on its own dedicated OS thread (serve_vm_hot_rpcs) locking only its own VmState — hot sync-RPCs + process-event drain — so the single dispatch task no longer serializes cross-VM pickup latency. Dedicated std::thread per VM (not a tokio task): the loop blocks on the VM's std::sync::Mutex, and a shared tokio worker pool starves under that contention. Main dispatch stays single-thread and, under SX_PARALLEL_VMS, skips VM polling and only drains forwarded (non-hot) events.

Unblocked by making the VFS mount boundary Send: MountedFileSystem: Any + Send, Send bound on impl VirtualFileSystem mount params, Box<dyn MountedFileSystem + Send>. Behavior-neutral; no plugin was non-Send. 85 sidecar lib + all kernel tests pass; full sidecar test binary compiles again (Arc<Mutex<VmState>> lock-site repairs in tests).

Also fixes a real latent deadlock surfaced by the restored test suite: configure_vm's rollback-error branch re-locked the same VM while its guard was held (reentrant std::Mutex → panic/deadlock); now writes deny_all through the live guard.

MEASUREMENT STATUS (honest): the boot harness never plumbed SX_PARALLEL_VMS to the sidecar (missing from docker -e + inside-measure env prefix — fixed here), so every prior 'concurrent 5/5' number ran with per-VM threads OFF. The first real per-VM-ON boot shows a SYSTEMATIC panel-only stall (render funnels through one single-threaded Xvfb; the always-polling per-VM threads oversubscribe CPU + contend the Xvfb lock). Net: this increment is NOT yet a validated boot win; SX_PARALLEL_VMS stays OFF by default pending a clean-machine A/B. The Send refactor, deadlock fix, test repairs, and env plumbing are unconditional improvements.
@NathanFlurry NathanFlurry force-pushed the wasm-gui-desktop branch 2 times, most recently from c0d50c5 to 1fe460a Compare July 5, 2026 21:23
…burst plumbing + Xvfb-throughput finding

- Env-tunable readiness-gated launch orchestration: SX_INFRA_DBUS_MS / SX_INFRA_SVC_MS / SX_WM_FALLBACK_MS / SX_LAUNCH_STAGGER_MS (defaults preserve prior behavior). Quiet-gate launch documented as the reliable path (a true concurrent burst starves the single-threaded Xvfb).
- SX_BURST_LAUNCH=1: launch all apps concurrently after WM-ready — an Xvfb fb-write stress option.
- Fix boot-harness env plumbing: SX_PARALLEL_VMS, SECURE_EXEC_T1_RING, and the SX_INFRA/WM/STAGGER/BURST vars were never forwarded to the sidecar/host (absent from measure-boot.sh docker -e AND inside-measure.sh host-env prefix), so prior 'concurrent' measurements silently ran with those levers OFF. Now plumbed.
- Xvfb-throughput investigation (SECURE_EXEC_T1_RING, the SAB bulk fb-write): a modest reliability win for the settle-gated boot under load (3/4 vs 1/4 FULL), but NOT the <=15s unlock and does NOT fix the per-VM regression. The real blocker is concurrent guest init, not fb-write throughput. All levers stay OFF by default; see PARALLEL-SERVICING-PLAN.md + progress artifacts.
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