Skip to content

Document wasi:http p3 instance reuse #898

Open

Description

@dicej

@tschneidereit and I have had informal discussions about host implementations reusing a given instance to handle multiple incoming requests by default for wasi:http@0.3.0 and beyond, and currently Wasmtime does this.

However, I don't know that this has been documented anywhere in the spec, nor do we yet have clear guidelines on how a component could opt out of reuse (e.g. with some combination of backpressure.dec, graceful shutdown, and wasi:cli/exit#exit). This would be helpful for both host and guest implementors.

Note that I'm mostly thinking of inbound wasi:http handlers here, but reuse can also be relevant for arbitrary components, so I'm not totally sure where this sort of thing should be specified.

Also note that this overlaps with, but is distinct from, #807, which concerns instances meant to run indefinitely, whereas this is about hosts reusing instances only a short time as an optimization which guest components should not rely heavily on for correctness.

Activity

  1. posborne commented on May 12, 2026

    @posborne

    I'll add that I found navigating this space to be a bit challenging to sort out without documentation and there seems to potentially be a gap in being able to clearly and correctly express 3 different cases for instance reuse using wasi-http (and latest wasmtime serve).

    The cases I tried to demonstrate in my test were the following, along with notes. There's very likely to be some user error here as I am just working to come more completely up to speed on some aspects of cm async and the p3 proposals:

    1. Concurrent instance reuse (the default).
    2. Serial instance reuse (one request at a time, but same instance).
      • I was able to show this working by having handle increment backpressure on entry and decrement.
      • This worked in my test case, but it wasn't entirely clear that this would unequivocally prevent a host from concurrently starting another asynchronous request (let's say two requests had come in). Would this be something guaranteed by the spec such that it would be incorrect for a host do this.
      • I did experiment with having a guest where the wit-bindgen export was "-" to do a sync lift; this compiled but did not work with wasmtime serve and wit-bindgen 0.55.0 1. This might be a wit-bingen issue, but I haven't dug in deep.
    3. No reuse (process one request and terminate).
      • I couldn't get a version of this to work (without changing the host to work in this mode).

    Footnotes

    1. Logs or sync lift case; I can share the full example if it is useful -- pretty basic handler that is an async fn with wit-bindgen having the export as "-export:wasi:http/handler@0.3.0-rc-2026-03-15#handle".

      Guest log:
      [sync-lift]  iid=0x831ad21dec08c719 req=01 START
      [sync-lift]  iid=0x831ad21dec08c719 req=01 END
      
      thread '<unnamed>' (1) panicked at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13:
      assertion failed: !task.is_null()
      note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
      worker error: error while executing at wasm backtrace:
        0:   0xb9f3 - abort
                        at wasisdk://v30.0/build/sysroot/wasi-libc-wasm32-wasip2-build-prefix/src/wasi-libc-wasm32-wasip2-build-build/wasisdk://v30.0/src/wasi-libc/libc-bottom-half/sources/abort.c:5:3
        1:   0x92f3 - std[d123b7a1a2ed1472]::sys::pal::wasi::helpers::abort_internal
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/pal/wasi/helpers.rs:4:14
        2:   0x8426 - std[d123b7a1a2ed1472]::process::abort
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/process.rs:2533:5
        3:   0x89f8 - __rustc[b7974e8690430dd9]::__rust_abort
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:33:5
        4:   0x74a9 - __rustc[b7974e8690430dd9]::__rust_start_panic
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/panic_abort/src/lib.rs:50:5
        5:   0x8825 - __rustc[b7974e8690430dd9]::rust_panic
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:886:25
        6:   0x7c9a - std[d123b7a1a2ed1472]::panicking::panic_with_hook
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:850:5
        7:   0x787a - std[d123b7a1a2ed1472]::panicking::panic_handler::{closure#0}
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:691:13
        8:   0x780d - std[d123b7a1a2ed1472]::sys::backtrace::__rust_end_short_backtrace::<std[d123b7a1a2ed1472]::panicking::panic_handler::{closure#0}, !>
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:182:18
        9:   0x8adb - __rustc[b7974e8690430dd9]::rust_begin_unwind
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
       10:  0x1057c - core[6d9e98711c484d2e]::panicking::panic_fmt
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14
       11:  0x103c9 - core[6d9e98711c484d2e]::panicking::panic
                        at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:150:5
       12:   0x4dd6 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::register_waker::hde47cb997528dce8
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13
                    - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete_with_code::hd22a90f526e6d1de
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:338:18
       13:   0x57a5 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete::h605a2b23cc93fc87
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:293:14
       14:   0x5c81 - <wit_bindgen::rt::async_support::future_support::RawFutureWrite<O> as core::future::future::Future>::poll::hc72fcaed7ea6645c
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:716:14
                    - <wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::DeferredWrite<O> as alloc::task::Wake>::wake::he1249cadca69f382
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:554:62
       15:   0x5a79 - wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::h235167da4f91e4a1
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:506:10
                    - <wit_bindgen::rt::async_support::future_support::FutureWriter<T> as core::ops::drop::Drop>::drop::hcaaad8d86644138a
                        at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:379:17
                    - core::ptr::drop_in_place<wit_bindgen::rt::async_support::future_support::FutureWriter<core::result::Result<core::option::Option<wasi_http_concurrency_guest::wasi::http::types::Fields>,wasi_http_concurrency_guest::wasi::http::types::ErrorCode>>>::h606931453b035b43
                        at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
                    - core::mem::drop::hf433209343d7ac34
                        at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/mem/mod.rs:975:1
                    - <wasi_http_concurrency_guest::Component as wasi_http_concurrency_guest::exports::wasi::http::handler::Guest>::handle::h74ebd70f1b9d8869
                        at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:204:9
       16:   0x2218 - wasi_http_concurrency_guest::exports::wasi::http::handler::_export_handle_cabi::h30c4ecad9fbc835d
                        at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
       17:   0x62a2 - wasi:http/handler@0.3.0-rc-2026-03-15#handle
                        at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
      error: channel closed
      Stack backtrace:
       0: <std::backtrace::Backtrace>::capture
       1: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
       2: wasmtime_cli::commands::serve::ServeCommand::serve::{{closure}}::{{closure}}
       3: tokio::runtime::task::raw::poll
       4: tokio::runtime::scheduler::multi_thread::worker::Context::run_task
       5: tokio::runtime::task::raw::poll
       6: std::sys::backtrace::__rust_begin_short_backtrace
       7: core::ops::function::FnOnce::call_once{{vtable.shim}}
       8: <std::sys::thread::unix::Thread>::new::thread_start
       9: __pthread_cond_wait
      
      ↩
  2. tschneidereit commented on May 12, 2026

    @tschneidereit
    Member

    This worked in my test case, but it wasn't entirely clear that this would unequivocally prevent a host from concurrently starting another asynchronous request (let's say two requests had come in). Would this be something guaranteed by the spec such that it would be incorrect for a host do this.

    Yes, signaling backpressure is meant to guarantee that no additional requests will be sent to the instance, and I believe that's what's implemented for wasmtime serve.

    No reuse (process one request and terminate).

    * I couldn't get a version of this to work (without changing the host to work in this mode).
    

    You should be able to opt out of reuse in the guest by calling exit, after which the guest can't be assumed to be in a good state to continue running.

  3. alexcrichton commented on May 12, 2026

    @alexcrichton
    Contributor

    This might be a wit-bingen issue, but I haven't dug in deep.

    Yeah this is a wit-bindgen issue having to do with and async function expecting ambient state to be configured but it's not because it wasn't entered from an async context. Something we definitely need to improve for wit-bindgen. If you're willing would you be up for filing an issue on wit-bindgen? No need to be too too detailed.

  4. posborne commented on May 12, 2026

    @posborne

    You should be able to opt out of reuse in the guest by calling exit, after which the guest can't be assumed to be in a good state to continue running.

    @tschneidereit It turns out cli:exit was working. The wasmtime serve host was logging clean exits as errors which mislead me.

    bytecodealliance/wasmtime#13345 patches the logging behavior.

  5. tschneidereit commented on May 13, 2026

    @tschneidereit
    Member

    The wasmtime serve host was logging clean exits as errors which mislead me.

    Ah yes, I keep running into that and meaning to file an issue for it. Would you mind opening one?

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

    P-httpProposal: wasi-http

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions