wasm32-wasip2 support: use wstd#4498
Conversation
044a2ad to
dd8fbd3
Compare
|
Sorry, took me a few weeks to get to this. Spent some time yesterday massaging the CI. That mostly looks good. The only error that seems related to this PR is here where That test is triggered by the tools/ci-scripts/check-aws-sdk-standalone-integration-tests script, specifically this chunk at the bottom: pushd "${tmp_dir}/aws/sdk/integration-tests/webassembly-no-os" &>/dev/null
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' cargo test --target wasm32-unknown-unknown --release
cargo test --target wasm32-wasip2 --release
popd
pushd "${tmp_dir}/aws/sdk/integration-tests/webassembly-wstd" &>/dev/null
cargo test --target wasm32-wasip2 --release
popdAny idea what might be going on there? Currently all of the utilities in The other failing CI task for the smoke tests seems unrelated to this PR, so I wouldn't worry about that. |
|
Thanks, and no worries we all have plenty on our plates. I was out sick last week and just got thrown a high priority item I'll need to put ahead of this for the moment... Which of the 3 |
This hopefully links to the log line where that is invoked. And this should be a link to the first line of the failure. |
|
@landonxjames I just got back to this. I can reproduce the CI failure on my machine with rust 1.91.0, but it does not occur under rust 1.91.1. Therefore, I believe the root cause of this issue is a bug that went out in 1.91.0 and was resolved in 1.91.1: See https://blog.rust-lang.org/2025/11/10/Rust-1.91.1/#linker-and-runtime-errors-on-wasm and rust-lang/rust#148363 I don't believe there is a good way to fix this bug in the source code, and the best mechanism is for this repo to update its rust version. I don't know what it entails to update this repo beyond just editing |
|
I pushed a commit that makes an uneducated attempt to upgrade the rust version, but it looks like it needs approval to run. Feel free to delete that commit, or I will, if its not the right way to do things - just wanted to see if CI would get to the next error or succeed... |
|
Looks like all the CI is about to pass and I am about to log off for the night, so kicked off a Canary run against this PR: https://github.com/smithy-lang/smithy-rs/actions/runs/22406654650 The Canary uses the WASI HTTP client to make some actual S3 calls, so this should be the final test to ensure that it all works correctly in a real environment. |
|
Canary run failed: logs (relevant bits pasted at the end of this comment) Code for the WASM Canary: https://github.com/smithy-lang/smithy-rs/tree/main/tools/ci-cdk/canary-wasm Code that loads the WASM binary, creates an instance of Wasmtime, and uses it to run the test: https://github.com/smithy-lang/smithy-rs/blob/main/tools/ci-cdk/canary-lambda/src/latest/wasm_canary.rs Instructions for running canary locally: https://github.com/smithy-lang/smithy-rs/blob/main/tools/ci-cdk/canary-lambda/README.md Have not yet confirmed if this reproduces locally, and note that running the canary does actually put/get objects from S3 so there is an associated cost. I'll try to devote some time to reproducing this this week. |
|
Thanks, I really appreciate how much time you've spent on plugging through the toolchain upgrade. I'd be totally lost without you. Without digging deep into the reproduction locally, just by inspection of the stack trace and the canary-wasm source code, its using the tokio executor to poll primitives (AsyncPollable) that can only be polled under the wstd executor, which won't ever work.
Update, now that I understand the canary system better it looks like this is deliberately component (wasip2) only, so I can fix it and additionally a cleanup couple of things that are leftover from the cargo-component era, which should simplify it. (Since the no-os stuff was never actually canaried, I'm not going to attempt to address that.) |
|
I've pushed the smallest possible fix. I chose not to unwind the cargo-component bits that return the list of objects over the component model, though we could simplify that by printing them to stdout since all the test does is assert that its not empty, and eliminate a bunch of bindgen boilerplate on the guest and host. but, things work fine with it anyway. Running locally with wasmtime-cli instead of the lambda machinery, I can see that it does work: |
|
Kicking off another canary run at: https://github.com/smithy-lang/smithy-rs/actions/runs/22461102015 And it passed, so this PR is more or less good to go. I will clean up a few more CI related things and get it shipped. Thanks for all the work and for being willing to upstream this @pchickey! |
Motivation and Context
This change is a follow-on to #4477, which added some basic support for the wasm32-wasip2 target using wasi-http interfaces. I discussed these changes with @landonxjames as they worked on 4477 and some of my feedback made it into that PR; this is a follow-on for more substantial contributions. For context, I am a maintainer of Wasmtime and wstd, and served as co-chair of the WASI standard subgroup for the development and release of wasip2.
In 4477, support for wasip2 is provided as an
impl HttpClientagainst the wasip2 platform's wasi-http interface, using only synchronous Rust calls. Then, in order to run the sdk under async rust, the test harness instantiates a single-threaded tokio runtime.The wasip2 target has very limited support for and in the tokio runtime:
spawn_blockingare impossible to implement for wasip2pollableresources, whereas the tokio event loop waits on operations on file descriptors. While wasip2's libc can provide tokio with the ability to wait on file and socket operations, but the wasi-http interface does not have any sort of libc file descriptor based interface, so the operations that we'd want an event loop to be able to poll on (such as: the response to an http request becoming ready, or streaming the contents of incoming or outgoing http bodies) are not available to the tokio event loopIn response to problems 1 and 2 being a sticking point for the Rust async ecosystem on wasip2, Bytecode Alliance contributors created wstd. Our expectation is that the upcoming release of the wasip3 target will provide solutions to problem 1, and we will work with the tokio project in the medium term to resolve problem 2. Until then, wstd is intended to fill the gap of providing an async executor that works natively for wasip2, and provides abstractions on top of wasip2 interfaces like wasi-http in idiomatic Rust terms. Effectively, wstd::http provides
http::{Request, Response}andhttp_body::Bodybased implementations of the same functionality that #4477 provided forimpl HttpClient, except that all of the operations that wait on the host use Futures to wait on the host using pollable.In fact, because interop with the AWS Rust SDK is so important, I had already published the
wstd-awscrate to make it very simple to use the SDK on the wasip2 target with wstd. This is more or less an upstreaming of that crate to be provided byaws-smithy-wasm, and under the license terms of the AWS Rust SDK instead of wstd-aws. I am the sole author ofwstd-aws, so I am able to relicense its contents as part of this PR.This is my first contribution to any of the AWS SDK or Smithy family of projects, so I may need guidance to navigate the CI and PR process here- thanks!
Description
This PR:
HttpConnectorandHttpClientinaws-smithy-wasm, as created in Landonxjames/wasm tests #4477, to use the wstd crate instead.AsyncSleeptoaws-smithy-wasmusing wstd as well. This makes it possible for timeouts or retries to work correctly.aws/sdk/integration-tests/{webassembly => webassembly-no-os}, keeping the contents of this test the same. This test preserves the existing behavior (crated in Landonxjames/wasm tests #4477) onwasip2of using a single-threaded tokio executor to execute tests, even though internally the new the wstdHttpClientimpl is used. My best judgement would be to get rid of this aspect of webassembly-no-os and just have it test that thewasm32-unknown-unknownintegration and target works, because this happening to work right now seems very fragile to me and is not how we should expect anyone to actually use this library.aws/sdk/integration-tests/webassembly-wstd, which is a copy of the wasip2 functionality fromwebassembly-no-osexcept with all of the fixes to fully exercise theAsyncSleepimplementation, meaning config no longer has to disable timeouts and retries. This is created as new crate because it requires a different set of cargo features to fully disable use of tokio at runtime. Tokio remains a dependency of this test build because not all of the aws-smithy- crates use tokio as an optional dependency properly - I can fix that in this PR, or in a follow-up PR, if desired, but that struck me as a much more involved and invasive change that I'd want to discuss with maintainers first.Testing
The new
aws/sdk/integration-tests/webassembly-wstdtest exercises all of the new functionality introduced inaws-smithy-wasm.Checklist
.changelogdirectory, specifying "client," "server," or both in theapplies_tokey..changelogdirectory, specifying "aws-sdk-rust" in theapplies_tokey.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.