Skip to content

wasi-http: p3 single-instance-per-request coverage and fixes#13345

Open
posborne wants to merge 1 commit into
bytecodealliance:mainfrom
posborne:wasi-http-cli-exit-0-not-error
Open

wasi-http: p3 single-instance-per-request coverage and fixes#13345
posborne wants to merge 1 commit into
bytecodealliance:mainfrom
posborne:wasi-http-cli-exit-0-not-error

Conversation

@posborne
Copy link
Copy Markdown
Collaborator

When a guest calls wasi:cli/exit(ok) from within a wasi:http/handler instance, the host exit implementation returns Err(I32Exit(0)). This propagated as a worker error, causing wasmtime serve to log a spurious "worker error" message and wasm backtrace on what is actually a clean, guest-controlled shutdown.

@posborne posborne requested a review from a team as a code owner May 12, 2026 23:13
@posborne posborne requested review from pchickey and removed request for a team May 12, 2026 23:13
@alexcrichton
Copy link
Copy Markdown
Member

Thanks! Could a test be added for this as well? For example crates/test-programs/src/bin/p3_cli_serve_hello_world.rs and related similar programs are how we're currently testing wasmtime serve

@posborne
Copy link
Copy Markdown
Collaborator Author

Thanks! Could a test be added for this as well? For example crates/test-programs/src/bin/p3_cli_serve_hello_world.rs and related similar programs are how we're currently testing wasmtime serve

Yeah, I'll add a test for this general case (one request per session) -- the change here just removes error logging in the non-error case but coverage would be useful even if it isn't asserting on log non-existence.

@posborne posborne requested a review from a team as a code owner May 13, 2026 23:07
@posborne
Copy link
Copy Markdown
Collaborator Author

@alexcrichton In doing these tests, I think I found a related bug that breaks use of the future returned by response.new intended to indicate when trasmission of the response is complete.

Currently, in wasmtime, it is possible for this to indicate completion before the bytes have been handed off to hyper. If the guest keys off this to exit, then bytes are dropped on the floor. Here I have pushed 3 additional commits:

  1. A basic test showing/covering how to use wasi-http with single-request-per-instance via backpressure and cli:exit. This test only fails spuriously due to the race on the response actually being handed off prior to repsonse future resolution.
  2. A test case that consistently reproduces the spurious failure from 1.
  3. A patch to the serve implementation that changes the behavior to make these tests pass.

The final patch in the series (dfe3349) I'm not entirely particularly confident in as I don't feel I have a confident grasp on the various futures going on and where/how errors in this chain might be involved.

@tschneidereit It sounds like you've also been doing some work with cli:exit and wasi-http -- do the test cases here make sense and have you seen similar results? Is the approach taken in my tests a valid use of the future provided by response.new?

@posborne posborne changed the title wasi-http: treat I32Exit(0) as graceful worker exit in P3 handler wasi-http: p3 single-instance-per-request coverage and fixes May 13, 2026
@alexcrichton alexcrichton requested review from alexcrichton and removed request for pchickey May 13, 2026 23:15
Copy link
Copy Markdown
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Everything here looks reasonable to me, but I also get tangled up in the futures here. CI looks like it's failing also on a channel/future-related thing which seems like it might be either a preexisting race or one accidentally introduced here?

Comment thread src/commands/serve.rs Outdated
Comment on lines +1218 to +1224
// Resolve the guest's `tx_result` future (returned by `response.new`)
// when hyper has finished reading the response body, not at
// request-resource cleanup time. Previously `request_io_result` was
// passed here, which resolved `tx_result` before the body had been
// handed off to hyper. A guest that calls `exit(ok)` after awaiting
// `tx_result` would therefore tear down the store while the body was
// still in flight.
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.

It's ok to drop the mention of the old code here, no need to document what-once-was and I think the first part of these docs stand well on their own

@posborne
Copy link
Copy Markdown
Collaborator Author

CI looks like it's failing also on a channel/future-related thing which seems like it might be either a preexisting race or one accidentally introduced here?

I'm working on reproducing this; it's similar to some of the kind of races I saw in the existing code which I had hoped had been addressed but some more digging is clearly warranted.

@alexcrichton
Copy link
Copy Markdown
Member

@posborne the most recent commit looks reasonable to me, but did you want to test/adjust more other than that? If not this'll need a rebase after #13404, and if so just lemme know when you feel this is ready

@posborne
Copy link
Copy Markdown
Collaborator Author

@alexcrichton I think it's ready to go, was just waiting on CI yesterday -- I did get a local repro so was fairly confident in the patch.

I can do the rebase and put it into the merge queue when ready.

When a guest calls wasi:cli/exit(ok) from within a wasi:http/handler
instance, the host exit implementation returns Err(I32Exit(0)).  This
propagated as a worker error, causing wasmtime serve to log an error and
close queued request channels rather than creating fresh instances.

I32Exit(0) semantically means 'this instance is done cleanly'.  Treat it
as a graceful worker exit rather than an error in the Worker::run path,
allowing guests to opt out of instance reuse via the exit+backpressure
pattern described in WebAssembly/WASI#898.

In addition to not logging an error, this patch also changes the signal
used to indicate that the response has been transmitted (as returned
to the guest by response.new) to be tied to the lifetime of the
response.  This avoids races that were previously present on the
handoff of responses to the http stack and notifications to the
guest of response transmission (which caused issues when exiting
from this signal).

Tests are added related to the single-request-per-instance
pattern that had previously failed and was racy.
@posborne posborne force-pushed the wasi-http-cli-exit-0-not-error branch from ee9bafc to 97819d9 Compare May 27, 2026 20:36
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.

2 participants