Skip to content

compiler: support panic/recover in Wasm without exceptions, plus explicit unwinding - #5550

Open
jakebailey wants to merge 8 commits into
tinygo-org:devfrom
jakebailey:wasm-panic-recover
Open

compiler: support panic/recover in Wasm without exceptions, plus explicit unwinding#5550
jakebailey wants to merge 8 commits into
tinygo-org:devfrom
jakebailey:wasm-panic-recover

Conversation

@jakebailey

@jakebailey jakebailey commented Jul 24, 2026

Copy link
Copy Markdown
Member

This is one of my crazier ideas; what if, instead of Wasm exceptions, we instead abuse the unwinding asyncify already slaps onto Wasm in order to unwind and recover panics?

Lo and behold, it works.

Truth be told, this is a lot of cleanup of copilot jank, but I don't hate what's here, especially because the binary overhead on top of asyncify is not all that bad; for the tsgo binary, this adds 5% and makes panic/recover/Goexit work!

On top of this is an "explicit" unwinder setting; it's not much work to basically enable a manual unwinding transform that works for any platform that doesn't have native unwinding. This can be used even on Wasm + scheduler=none. But since the cost of this is fairly high, it's not on by default.

The performance of this seems to not be bad; given one already does asyncify and this just piggy backs on top of that, there's not much more work being done besides in defer blocks to actually check for panic and then recover.

When WASI 0.3 comes along, none of this will matter, since I think Wasm exceptions "just work". But I think this does open the door to current users.

(I did notice that RISCV64 is a platform without native unwinding... not sure why that's the case, but I feel like a separate PR could totally just enable that, in which case all of this would really only be for Wasm and I guess "xtensa", not that I really know what that is.)

I suppose this fixes #2914?

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds return-based panic/Goexit unwinding support to TinyGo, enabling panic/recover (and Goexit deferred execution) on WebAssembly without relying on Wasm exceptions, and introducing an opt-in “explicit” unwinding mode for targets without native unwinding.

Changes:

  • Introduces a return-based unwind signal mechanism in the runtime (asyncify- and explicit-driven) and threads it through panic/recover/Goexit paths.
  • Updates the compiler to propagate unwind via inserted post-call checks, new asyncify “catch” wrappers for defer contexts, and adjusted fault/panic lowering.
  • Expands coverage with new/updated tests and testdata outputs, and updates standard library package test allowlists accordingly.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
transform/unwind.go Adds an LLVM llvm.assume insertion pass to help optimize away redundant unwind checks for asyncify-based unwinding.
transform/unwind_test.go Adds a focused transform test that runs an LLVM pipeline to validate unwind assumption effects.
transform/transform_test.go Threads PanicUnwind through the test compiler configuration.
transform/testdata/unwind.ll Adds IR input for testing AddUnwindAssumptions.
transform/testdata/unwind.out.ll Adds expected IR output demonstrating llvm.assume insertion and optimization effects.
transform/optimizer.go Runs AddUnwindAssumptions during optimization when using asyncify-based unwinding.
tests/testing/pass/pass_test.go Adds runtime tests exercising deferred behavior around suspension and concurrency.
testdata/testing.go Enables additional subtests on wasm now that Goexit/fatal/skip semantics are supported.
testdata/testing-wasm.txt Updates wasm expected output to reflect newly enabled subtest behavior.
testdata/recover.go Adds additional recover test cases for interface comparison and map key/runtime-error paths.
testdata/recover.txt Updates expected output for new recover test cases.
testdata/recover-explicit.go Adds a minimal explicit-unwind recover test program.
testdata/recover-explicit.txt Adds expected output for the explicit-unwind recover test.
testdata/goexit.go Adds a Goexit case that verifies deferred code runs (including under -panic=trap).
src/runtime/panic.go Refactors panic/Goexit to a common unwind start path and tracks unwind state in the defer frame.
src/runtime/panic_unwind_signal_unicore.go Adds unwind signal storage/accessors for unicore (non-threads/non-cores) schedulers.
src/runtime/panic_unwind_signal_cores.go Adds per-core unwind signal storage/accessors for scheduler.cores + explicit unwinding.
src/runtime/panic_unwind_setjmp.go Provides startUnwind implementation for setjmp/longjmp targets.
src/runtime/panic_unwind_return.go Implements return-based unwindPending/clearUnwind helpers for explicit/asyncify modes.
src/runtime/panic_unwind_none.go Provides a no-op startUnwind for targets without unwinding.
src/runtime/panic_unwind_explicit.go Implements explicit return-based startUnwind (sets signal + marks frame).
src/runtime/panic_unwind_asyncify.go Implements asyncify-driven startUnwind (sets signal + triggers asyncify unwind).
src/internal/task/task_asyncify.go Adds a synchronous “panic unwind” entrypoint that triggers asyncify unwind without pausing/switching tasks.
compiler/map.go Uses invoke-style runtime calls for panic-capable generic map operations under unwind modes.
compiler/interface.go Routes interface assertion failures through invoke/unwind return handling instead of unconditional unreachable.
compiler/defer.go Makes recover support depend on configured unwind mode; clears unwind state at landing pads and after deferred calls; adds suspend-aware deferred invocation.
compiler/compiler.go Adds PanicUnwind to compiler config and integrates unwind-aware lowering behavior (post-call checks, unwind return blocks).
compiler/compiler_test.go Threads PanicUnwind into compiler test configuration.
compiler/calls.go Adds suspend analysis and asyncify catcher wrappers; introduces unwind propagation checks and unwind return block creation.
compiler/asserts.go Routes runtime assert failures through invoke/unwind return handling instead of unconditional unreachable.
compileopts/target.go Adds panic-unwind to target specs and validates allowed values.
compileopts/target_test.go Adds tests for PanicUnwind() configuration resolution rules.
compileopts/options.go Adds -panic-unwind option validation.
compileopts/options_test.go Adds option verification tests for -panic-unwind.
compileopts/config.go Adds unwind build tags and implements PanicUnwind()/SupportsExplicitUnwind() selection logic.
builder/config.go Enforces invalid scheduler/unwind combinations (e.g. explicit + asyncify/threads) at config creation time.
builder/build.go Threads PanicUnwind into the compiler configuration used for builds.
main.go Adds -panic-unwind CLI flag and plumbs it into build options.
main_test.go Enables recover tests on wasm and adds explicit-unwind wasm test coverage; updates wasm import expectations and adds Goexit/defers coverage.
GNUmakefile Updates standard library test package allowlists and related skip notes based on improved recover/Goexit support.
builder/sizes_test.go Updates expected binary sizes due to changed codegen/runtime behavior.
compiler/testdata/basic.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).
compiler/testdata/func.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).
compiler/testdata/generics.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).
compiler/testdata/go1.20.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).
compiler/testdata/large.ll Updates expected IR for unwind-aware defer lowering, asyncify catcher generation, and unwind propagation behavior.
compiler/testdata/slice.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).
compiler/testdata/string.ll Updates expected IR to return via an unwind path after panic sites (instead of unreachable).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread compiler/calls.go
@jakebailey
jakebailey force-pushed the wasm-panic-recover branch from a004f53 to 5718917 Compare July 24, 2026 13:58
@jakebailey

Copy link
Copy Markdown
Member Author

The runner is timing out on regexp/syntax tests, which I now unskip. I'll figure out if this is a bug or just them being too slow on riscv-qemu.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 48 out of 48 changed files in this pull request and generated no new comments.

Add unwind modes for propagating panic and Goexit without relying on
exception handling. Keep setjmp unwinding on existing native targets and
use Asyncify automatically when the Asyncify scheduler is selected.

Stop Asyncify panic unwinding at the nearest defer frame, then run its
deferred calls. Allow ordinary scheduler suspension to pass through the
same frame, preserving aggregate results across rewind and nested or
concurrent task execution.

Add -panic-unwind=auto|explicit. Auto leaves targets without setjmp or
Asyncify unchanged, while explicit opts wasm32, riscv64, and Xtensa into
return-based unwinding. The trap panic strategy still traps panics
immediately, but unwind support remains available for Goexit.

Enable recovery, Goexit, and testing package coverage on WebAssembly and
WASI targets that use Asyncify.
Move the standard library packages that were blocked by missing panic
recovery into the portable test set. Keep image excluded from bare wasm
because its tests require filesystem fixtures.

Also enable crypto/ecdsa in the fast WASI suite now that Goexit runs
deferred calls.
Exercise explicit return-based unwinding through nested and deferred
panics, repanics, indirect calls, scalar and aggregate results, and
runtime-generated faults.

The fixture runs with the scheduler disabled on each WebAssembly target.
@jakebailey
jakebailey force-pushed the wasm-panic-recover branch from 1e2d7eb to abd56c9 Compare July 25, 2026 06:26
@jakebailey
jakebailey marked this pull request as ready for review July 25, 2026 14:26
Comment thread compiler/calls.go Outdated
suspendYes
)

func (b *builder) functionMaySuspend(fn *ssa.Function) bool {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this logic needed?
We should have this information already in the createInvoke vs createCall difference:

tinygo/compiler/calls.go

Lines 98 to 102 in 8b3200c

func (b *builder) createInvoke(fnType llvm.Type, fn llvm.Value, args []llvm.Value, name string) llvm.Value {
if b.hasDeferFrame() {
b.createInvokeCheckpoint()
}
return b.createCall(fnType, fn, args, name)

(So this PR would basically not bail out in hasDeferFrame).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, you're actually traversing the call graph.
Perhaps it's a good idea to merge this logic with the createInvoke, because it would also help other architectures to skip some unwinding steps.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yeah, that's a good idea

@dgryski

dgryski commented Aug 4, 2026

Copy link
Copy Markdown
Member

This branch causes us to lose information about a stack trace during unwinding, which was really convenient for debugging.

For example,

~/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/sampleuv $ tinygo test -target=wasip1 -v
panic: unimplemented: (reflect.Type).IsVariadic()
Error: failed to run main module `/var/folders/yh/8gzm4zjj0zzdm60t2mm9mqkc0000gn/T/tinygo3242204435/main.wasmopt`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
    0:  0x23ea6 - runtime.panicOrGoexit
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:94:9
    1:   0x3697 - runtime._panic
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:56:15
    2:  0x19d5d - runtime.run$1
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:45:5
    3:  0x17960 - <goroutine wrapper>
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:264:2
    4:    0xa42 - tinygo_launch
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify_wasm.S:59:0
    5:  0x176f7 - (*internal/task.Task).Resume
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify.go:128:17
                - runtime.scheduler
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:233:11
                - runtime.run
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:269:11
                - _start
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/runtime_wasmentry.go:20:5
    2: wasm trap: wasm `unreachable` instruction executed

FAIL	gonum.org/v1/gonum/stat/sampleuv	0.116s

Vs previously:

~/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/sampleuv $ tinygo test -target=wasip1 -v
panic: unimplemented: (reflect.Type).IsVariadic()
Error: failed to run main module `/var/folders/yh/8gzm4zjj0zzdm60t2mm9mqkc0000gn/T/tinygo1645792135/main.wasmopt`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
    0:  0x1a197 - runtime.panicOrGoexit
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:83:9
    1:   0x2b4c - runtime._panic
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:55:15
    2:  0x30b3c - (*reflect.rawType).IsVariadic
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/reflect/type.go:477:7
    3:  0x5aa84 - (Go interface method)
    4:  0x5a9f0 - github.com/google/go-cmp/cmp/internal/function.IsType
                    at /Users/dgryski/go/pkg/mod/github.com/google/go-cmp@v0.6.0/cmp/internal/function/func.go:39:57
    5:  0x1917d - github.com/google/go-cmp/cmp.FilterValues
                    at /Users/dgryski/go/pkg/mod/github.com/google/go-cmp@v0.6.0/cmp/options.go:161:21
    6:  0x12824 - main!runtime.initAll
    7:  0x11662 - runtime.run$1
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:265:10
    8:  0x10e7b - <goroutine wrapper>
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:264:2
    9:    0x5c5 - tinygo_launch
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify_wasm.S:59:0
   10:  0x10d33 - (*internal/task.Task).Resume
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify.go:116:17
                - runtime.scheduler
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:233:11
                - runtime.run
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:269:11
                - _start
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/runtime_wasmentry.go:20:5
    2: wasm trap: wasm `unreachable` instruction executed
FAIL	gonum.org/v1/gonum/stat/sampleuv	0.100s

Can we do anything about this?

@jakebailey

Copy link
Copy Markdown
Member Author

I think I can do something tricky to preserve the original stack; will try when I have more time.

@dgryski

dgryski commented Aug 4, 2026

Copy link
Copy Markdown
Member

And in fact the corpus has a new failure:
dev:

~/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/mat $ tinygo test -target=wasip1  -v -run=TestHOGSVD
=== RUN   TestHOGSVD
--- PASS: TestHOGSVD (5.42s)
PASS
ok  	gonum.org/v1/gonum/mat	5.721s

This branch:

~/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/mat $ tinygo test -target=wasip1  -v -run=TestHOGSVD
=== RUN   TestHOGSVD
Error: failed to run main module `/var/folders/yh/8gzm4zjj0zzdm60t2mm9mqkc0000gn/T/tinygo2070389103/main.wasmopt`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
    0: 0x232b58 - main!<wasm function 2434>
    1:   0x1e79 - tinygo_rewind
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify_wasm.S:94:0
    2:  0x1ab18 - (*internal/task.Task).Resume
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify.go:131:17
                - runtime.scheduler
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:233:11
                - runtime.run
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:269:11
                - _start
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/runtime_wasmentry.go:20:5
    2: wasm trap: wasm `unreachable` instruction executed

FAIL	gonum.org/v1/gonum/mat	1.806s

@jakebailey

Copy link
Copy Markdown
Member Author

Yikes, I think I still have a bad bug. I think I'll have to address that crash with some more big changes

@jakebailey
jakebailey marked this pull request as draft August 4, 2026 23:12
@jakebailey

Copy link
Copy Markdown
Member Author

I fixed both (unrelated bugs), but it does seem like the bookkeeping for this adds about 64B to every frame, and that test happens to be on the edge of defaults. It can fail in the same way on a small enough stack even before any of my changes.

@jakebailey
jakebailey marked this pull request as ready for review August 5, 2026 01:53
@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

More corpus issues with gonum. Hard to necessarily pin-down on this, since this package wasn't run before on wasi, but the stack trace seems to suggest something new.

So, stat/distuv has some tests that fail with an OOM. TestPoisson is one, TestWeibull is another. The only fail in the middle of a test run, or if run with -count=10. The destroyDeferFrame is the suspicious part to me.

~/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/distuv $ tinygo test -target=wasip1 -v -count=10 '-run=TestPoisson$'
=== RUN   TestPoisson
--- PASS: TestPoisson (5.47s)
=== RUN   TestPoisson
--- PASS: TestPoisson (5.13s)
=== RUN   TestPoisson
--- PASS: TestPoisson (4.89s)
=== RUN   TestPoisson
--- PASS: TestPoisson (5.90s)
=== RUN   TestPoisson
--- PASS: TestPoisson (4.91s)
=== RUN   TestPoisson
--- PASS: TestPoisson (4.98s)
=== RUN   TestPoisson
--- PASS: TestPoisson (3.54s)
panic: out of memory
Error: failed to run main module `/var/folders/yh/8gzm4zjj0zzdm60t2mm9mqkc0000gn/T/tinygo3415911017/main.wasmopt`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
    0:  0x1fc30 - runtime.panicOrGoexit
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:94:9
    1:  0x1f930 - runtime.destroyDeferFrame
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:172:16
    2:  0x62898 - (*testing.T).Run$1
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:540:3
    3:  0x62666 - <goroutine wrapper>
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:537:2
    4:    0xdc6 - tinygo_launch
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify_wasm.S:59:0
    5:  0x16689 - (*internal/task.Task).Resume
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify.go:131:17
                - runtime.scheduler
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:233:11
                - runtime.run
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:269:11
                - _start
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/runtime_wasmentry.go:20:5
    2: wasm trap: wasm `unreachable` instruction executed

FAIL	gonum.org/v1/gonum/stat/distuv	34.904s

@jakebailey

Copy link
Copy Markdown
Member Author

Can you try these with a larger wasm stack? I think these are all just overflows...

@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

Just realized I wasn't on the latest version of your branch. I'm rerunning, and will try with a larger wasm stack.

@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

Better stack trace

--- PASS: TestPoisson (5.16s)
=== RUN   TestPoisson
fatal error: out of memory
Error: failed to run main module `/var/folders/yh/8gzm4zjj0zzdm60t2mm9mqkc0000gn/T/tinygo2657815517/main.wasmopt`

Caused by:
    0: failed to invoke command default
    1: error while executing at wasm backtrace:
    0:  0x137c8 - runtime.runtimeFatal
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/panic.go:119:9
    1:   0x9756 - runtime.alloc
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/gc_blocks.go:468:15
    2:  0x9707e - gonum.org/v1/gonum/stat/distuv.checkExKurtosis
                    at /Users/dgryski/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/distuv/distribution_test.go:116:13
    3:  0xdd744 - gonum.org/v1/gonum/stat/distuv.testPoisson
                    at /Users/dgryski/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/distuv/poisson_test.go:132:17
                - gonum.org/v1/gonum/stat/distuv.TestPoisson
                    at /Users/dgryski/go/src/github.com/dgryski/tinygo-test-corpus/_corpus/gonum/gonum/stat/distuv/poisson_test.go:116:14
    4:  0x5efc2 - main!(*testing.B).doBench$1.asyncifysuspendcatch.0.target
    5:  0x5ef3e - main!(*testing.B).doBench$1.asyncifysuspendcatch.0.paniccatch
    6:  0x62f80 - testing.tRunner
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:503:4
    7:  0x63d0f - main!(*testing.T).Run$1.asyncifysuspendcatch.0.target
    8:  0x63c78 - main!(*testing.T).Run$1.asyncifysuspendcatch.0.paniccatch
    9:  0x62ca5 - (*testing.T).Run$1
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:537:5
   10:  0x62af2 - <goroutine wrapper>
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/testing/testing.go:537:2
   11:    0xea3 - tinygo_launch
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify_wasm.S:65:0
   12:  0x16aff - (*internal/task.Task).Resume
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/internal/task/task_asyncify.go:181:17
                - runtime.scheduler
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:233:11
                - runtime.run
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/scheduler_cooperative.go:269:11
                - _start
                    at /Users/dgryski/go/src/github.com/tinygo-org/tinygo/src/runtime/runtime_wasmentry.go:20:5
    2: wasm trap: wasm `unreachable` instruction executed

I feel like something is leaking memory. This fails even with -gc=boehm and -stack-size=10MB.

@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

Hmm... maybe this test is just really memory hungry? It seems to allocate 412MB, but occasionally 912MB per iteration. Lowering the priority of this failure for now.

@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

Test corpus passes, with the exception of the above failure (which I'm pretty sure is just bizarrely hungry tests at this point and not necessarily indicative of a bug at this point.)

@dgryski

dgryski commented Aug 5, 2026

Copy link
Copy Markdown
Member

From a compatibility perspective, this allows way more tests in the test corpus to pass on wasi.

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.

Implement recover for wasm architecture

4 participants