Skip to content

fix(wasix): preserve core error recovery and limit SJLJ code growth - #229

Merged
f0rr0 merged 4 commits into
mainfrom
f0rr0/fix-wasix-core-error-recovery
Oct 1, 2026
Merged

f0rr0 merged 4 commits into
mainfrom
f0rr0/fix-wasix-core-error-recovery

Conversation

@f0rr0

@f0rr0 f0rr0 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

A PL/pgSQL error after COPY can close the connection or trap in __wasm_setjmp_test instead of returning its SQLSTATE. The WASIX libc sigsetjmp wrapper places the exception handler in a frame that has already returned when PostgreSQL calls siglongjmp.

  • Expand sigsetjmp into compiler-visible setjmp at single-user core call sites, extending the existing side-module fix.
  • Enable Wasm EH/SjLj at the backend relocatable link, where ThinLTO bitcode is lowered. Enabling it only at the final link is too late.
  • Set that partial link's inline threshold to zero to limit LLVM-generated catch-state spills and code duplication. Frontend and final-link optimization settings stay in place.
  • Add a client regression that alternates COPY, a PL/pgSQL error, and a successful query three times, checking SQLSTATE P0001, statement rollback, and connection reuse.

Fixes #227.

Includes the CI prerequisite fixes from #228: public Rust README documentation, source-only qualification, selected source uploads, and explicit WASIX consumer artifact dependencies. Merge #228 first to keep this PR focused on the five runtime/regression files.

Artifact size

Compared with the same correctness fix using the default partial-link inline budget:

Artifact Fix only This change Reduction
Core WASM 13,014,266 bytes 10,125,440 bytes 22.2%
Linux x86-64 AOT 31,461,048 bytes 26,305,272 bytes 16.4%
Compressed AOT 6,687,370 bytes 5,574,761 bytes 16.6%
Portable runtime archive 4,040,700 bytes 3,573,676 bytes 11.6%

The correctness fix alone grows WASM from 12,125,389 to 13,014,266 bytes. Analysis traced most of that growth to local loads and stores generated while lowering SjLj catch-state PHIs. The inline budget mitigates this compiler behavior; it does not fix LLVM's spill-placement algorithm.

Query performance tradeoff

Warm Linux x86-64 AOT SDK measurements, with identical SQL results and verified embedded runtime hashes:

Workload Fix only This change Change
SELECT 42 81.40 µs 81.36 µs −0.1%
Aggregate 1.957 ms 2.034 ms +3.9%
Join 6.688 ms 6.374 ms −4.7%
Sort 5.846 ms 5.948 ms +1.7%
JSON processing 21.294 ms 23.008 ms +8.0%
PL/pgSQL 798.01 µs 795.28 µs −0.3%

These are medians of batch-average call costs, including SDK handling and row decoding, from six processes per build in repeated ABBA order on one pinned CPU. They are not individual-request latency percentiles. JSON processing shows a consistent cost; the other measurements do not establish a general speedup. This is an explicit size/performance tradeoff. TCP, concurrent throughput, cold start, and p95/p99 were not measured.

Release Intent

  • Package/API/runtime change: PR title uses fix:.
  • Docs/CI/repository-only change: no release intended.
  • Source/input/runtime asset change: PostgreSQL/toolchain pins are unchanged; portable and Linux AOT assets were regenerated through the owning production tasks, including source fingerprints and package metadata. Generated artifacts are not committed.

Verification

  • Full Moon affected and cross-platform CI checks passed: pending PR CI.
  • Selected local owner checks passed: oliphaunt-pgwire-server:format-check, :lint, :test (26 tests), and :test-integration (12 tests).
  • Production liboliphaunt-wasix:runtime-aot dependency chain passed: source inputs, compiler output, strict portable packaging, and Linux x86-64 AOT packaging/verification.
  • liboliphaunt-wasix:smoke passed all seven PostgreSQL regression tests against the rebuilt runtime.
  • The new COPY/PLpgSQL regression fails against the published old runtime and passes against the rebuilt runtime.
  • Additional local probes exercised nested catches/rethrows, subtransaction and savepoint rollback, trigger failures, extended-protocol recovery, 100 alternating errors/successes, reopen, and CREATE DATABASE failure cleanup for both WAL_LOG and FILE_COPY. No unreachable traps occurred.
  • All 1,336 import/export names and signatures are preserved; PL/pgSQL loads successfully. Table capacity changes from 5,770 to 5,783.
  • Product artifact sizes and warm query performance were measured as described above.

The runtime size, performance, and local behavior measurements above used the exact tracked diff on base 32ce7b29510b74333e799601b69a71fd28122e80. Windows/macOS/ARM/browser qualification, the full extension lifecycle matrix, and the full TrailBase suite remain unverified locally. The host-recovery paths remain in place.

The updated head 429fac6c92671eeabb94367454a170c79ac4e285 includes current main and #228 through a linear history. Local release-intent and release-metadata checks pass; owner checks and full fresh CI qualification are still in progress. The runtime patches and COPY/error-recovery regression are unchanged. Earlier runtime measurements do not qualify the updated producer inputs.

@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
oliphaunt-docs Ready Ready Preview Oct 1, 2026 8:51am UTC

@f0rr0
f0rr0 force-pushed the f0rr0/fix-wasix-core-error-recovery branch from c12f800 to 429fac6 Compare October 1, 2026 08:50
@f0rr0
f0rr0 merged commit 0a8ed66 into main Oct 1, 2026
106 checks passed
@f0rr0
f0rr0 deleted the f0rr0/fix-wasix-core-error-recovery branch October 1, 2026 11:31

This branch was successfully deployed

1 active deployment
Preview — 429fac6c Deployed Oct 1, 2026 by vercel[bot]
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.

bug: unreachable reached

1 participant