Skip to content

GC panics while tracing a suspended stack-switching continuation #14239

Description

@rirze

Wasmtime version

This reproduces with Wasmtime 48.0.1 and current main at
d8a0da6d661605713798c1c9c76be5c28e3159ff.

Reproduction

With function references, exceptions, stack switching, and GC enabled, the
following test panics when guest allocations trigger GC while a continuation is
suspended:

#[cfg_attr(any(asan, miri), ignore)]
#[test]
fn gc_traces_a_suspended_continuation() -> Result<()> {
    let wat = r#"
        (module
            (type $ft (func))
            (type $ct (cont $ft))
            (type $st (struct (field i32)))
            (tag $t)

            (func $suspend
                (suspend $t)
            )
            (elem declare func $suspend)

            (func (export "entry")
                (local $continuation (ref null $ct))
                (local $i i32)
                (block $handler (result (ref $ct))
                    (resume $ct
                        (on $t $handler)
                        (cont.new $ct (ref.func $suspend)))
                    (return)
                )
                (local.set $continuation)
                (loop $allocate
                    (drop (struct.new $st (i32.const 7)))
                    (local.set $i (i32.add (local.get $i) (i32.const 1)))
                    (br_if $allocate (i32.lt_u (local.get $i) (i32.const 20000)))
                )
                (resume $ct (local.get $continuation))
            )
        )
    "#;

    test_utils::Runner::new().run_test::<()>(wat, &[])
}

Actual result

panicked at crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs:340:18:
expected one more VMStackLimits than continuations

The stack proceeds through gc_alloc_raw, do_gc,
trace_wasm_continuation_roots, trace_suspended_continuation, and
trace_through_continuations.

Expected result

GC should trace the suspended continuation and entry should complete normally.

Analysis

trace_through_continuations handles the current activation before walking its
ancestors. It advances the stack-limits iterator past that activation, but does
not advance the matching continuation iterator. The remaining iterators
therefore have different lengths.

Advancing continuations_iter once before making it peekable aligns it with the
existing stack-limits advance. The test above fails before that change and
passes afterward.

This appears distinct from #13750, which concerns missing stack maps for
continuation payload values. The broader stack-switching tracking issue is
#10248.

Environment

  • OS: Linux x86_64
  • Rust: 1.97.1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wasm-proposal:gcIssues with the implementation of the gc wasm proposalwasm-proposal:stack-switchingIssues related to WebAssembly stack switching

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions