Skip to content

wasm32-wasip2 support: use wstd - #4498

Merged
aws-sdk-rust-ci merged 23 commits into
smithy-lang:mainfrom
pchickey:wasm_use_wstd
Feb 27, 2026
Merged

wasm32-wasip2 support: use wstd#4498
aws-sdk-rust-ci merged 23 commits into
smithy-lang:mainfrom
pchickey:wasm_use_wstd

Conversation

@pchickey

@pchickey pchickey commented Jan 26, 2026

Copy link
Copy Markdown
Contributor

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 HttpClient against 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:

  1. wasip2 is only a single-threaded target, with no stack switching primitives available. This means that frequently-used tokio primitives such as spawn_blocking are impossible to implement for wasip2
  2. wasip2's primitives for waiting on operations external to the instance (roughly a process, in unix terms) are in terms of wasi-io pollable resources, 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 loop

In 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} and http_body::Body based implementations of the same functionality that #4477 provided for impl 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-aws crate 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 by aws-smithy-wasm, and under the license terms of the AWS Rust SDK instead of wstd-aws. I am the sole author of wstd-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:

  1. Switches the implementations of HttpConnector and HttpClient in aws-smithy-wasm, as created in Landonxjames/wasm tests #4477, to use the wstd crate instead.
  2. Adds an implementation of AsyncSleep to aws-smithy-wasm using wstd as well. This makes it possible for timeouts or retries to work correctly.
  3. Renames 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) on wasip2 of using a single-threaded tokio executor to execute tests, even though internally the new the wstd HttpClient impl is used. My best judgement would be to get rid of this aspect of webassembly-no-os and just have it test that the wasm32-unknown-unknown integration 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.
  4. Creates a new aws/sdk/integration-tests/webassembly-wstd, which is a copy of the wasip2 functionality from webassembly-no-os except with all of the fixes to fully exercise the AsyncSleep implementation, 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-wstd test exercises all of the new functionality introduced in aws-smithy-wasm.

Checklist

  • For changes to the smithy-rs codegen or runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "client," "server," or both in the applies_to key.
  • For changes to the AWS SDK, generated SDK code, or SDK runtime crates, I have created a changelog entry Markdown file in the .changelog directory, specifying "aws-sdk-rust" in the applies_to key.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@pchickey
pchickey requested a review from a team as a code owner January 26, 2026 16:40
@landonxjames
landonxjames requested a review from a team as a code owner February 12, 2026 20:24
@landonxjames

landonxjames commented Feb 13, 2026

Copy link
Copy Markdown
Collaborator

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 cargo test --target wasm32-wasip2 --release is failing for the webassembly-no-os integration test with a bunch of linker errors all generally of the form:

[78](https://github.com/smithy-lang/smithy-rs/actions/runs/21976834044/job/63493537582?pr=4498#step:4:25986)
          rust-lld: error: import module mismatch for symbol: [resource-drop]output-stream
          >>> defined as wasi:io/streams@0.2.9 in /tmp/smithy-rs-ci-01yxisGR/aws/sdk/integration-tests/target/wasm32-wasip2/release/deps/libaws_smithy_wasm-fa88541d645a5271.rlib(aws_smithy_wasm-fa88541d645a5271.aws_smithy_wasm.7fc4b04342a197e4-cgu.1.rcgu.o)
          >>> defined as wasi:io/streams@0.2.4 in /tmp/smithy-rs-ci-01yxisGR/aws/sdk/integration-tests/target/wasm32-wasip2/release/deps/libaws_config-3b549ec95c1362e2.rlib(aws_config-3b549ec95c1362e2.aws_config.fb880679318ea17e-cgu.01.rcgu.o)

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
popd

Any idea what might be going on there? Currently all of the utilities in aws-smithy-wasm are targeted at WASI environments, but I would like to make sure it continues building for wasm32-unknown-unknown to keep open the possibility of adding non-WASI utils in the future.

The other failing CI task for the smoke tests seems unrelated to this PR, so I wouldn't worry about that.

@pchickey

Copy link
Copy Markdown
Contributor Author

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 cargo test invocations you quoted gives an error in that form - all of them? or does it die on the first one?

@landonxjames

Copy link
Copy Markdown
Collaborator

Which of the 3 cargo test invocations you quoted gives an error in that form - all of them? or does it die on the first one?

cargo test --target wasm32-wasip2 --release fails in the integration-tests/webassembly-no-os crate.

This hopefully links to the log line where that is invoked. And this should be a link to the first line of the failure.

@pchickey

pchickey commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

@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 rust-toolchain.toml but I imagine there is more process than that, can you either do that for me or point me towards how to do it?

[p.hickey@KVKD0WG7VF:integration-tests/webassembly-no-os]% cargo +1.91.0 test --target wasm32-wasip2 --release
   Compiling webassembly-no-os v0.1.0 (/Users/p.hickey/src/smithy-rs/aws/sdk/integration-tests/webassembly-no-os)
   
... snip ...

          rust-lld: error: import module mismatch for symbol: [resource-drop]pollable
          >>> defined as wasi:io/poll@0.2.9 in /Users/p.hickey/src/smithy-rs/target/wasm32-wasip2/release/deps/libwstd-e0cdf862c7b5f7f9.rlib(wstd-e0cdf862c7b5f7f9.wstd.c5c79b594a6517-cgu.08.rcgu.o)
          >>> defined as wasi:io/poll@0.2.4 in /Users/p.hickey/.rustup/toolchains/1.91.0-aarch64-apple-darwin/lib/rustlib/wasm32-wasip2/lib/libstd-12861a9918591092.rlib(std-12861a9918591092.std.1d798d00e0a1ae89-cgu.0.rcgu.o)
          error: failed to invoke LLD: exit status: 1


error: could not compile `webassembly-no-os` (lib test) due to 1 previous error

[p.hickey@KVKD0WG7VF:integration-tests/webassembly-no-os]% cargo +1.91.1 test --target wasm32-wasip2 --release
    Finished `release` profile [optimized] target(s) in 0.45s
     Running unittests src/lib.rs (/Users/p.hickey/src/smithy-rs/target/wasm32-wasip2/release/deps/webassembly_no_os-1a7ca5a8ae542471.wasm)

running 5 tests
test wasm32_unknown_unknown::test::basic_operation_with_retries ... ok
test wasm32_unknown_unknown::test::no_sleep_impl - should panic ... ignored
test wasm32_unknown_unknown::test::no_time_source - should panic ... ignored
test wasm32_wasip2::test::basic_operation_with_retries_no_sleep_no_time ... ok
test wasm32_wasip2::test::test_operation_construction ... ok

test result: ok. 3 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 2.24s

@pchickey

Copy link
Copy Markdown
Contributor Author

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...

@landonxjames

landonxjames commented Feb 25, 2026

Copy link
Copy Markdown
Collaborator

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.

@landonxjames

Copy link
Copy Markdown
Collaborator

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.

:Future>::poll::h280adcdd6b23d855\n   16: 0x2840dd - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::http::body::minimum_throughput::MaybeUploadThroughputCheckFuture as core::future::future::Future>::poll::h03360f94a929bb3e\n   17:   0xc444 - aws_sdk_rust_lambda_canary_wasm.wasm!aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}::h826edc302a82caee\n   18:  0x3ba2c - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::timeout::MaybeTimeoutFuture<InnerFuture> as core::future::future::Future>::poll::h0da7aa80ff1c4e5d\n   19:  0x3e096 - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::timeout::MaybeTimeoutFuture<InnerFuture> as core::future::future::Future>::poll::h95b704f3404b7fbe\n   20:  0x1495c - aws_sdk_rust_lambda_canary_wasm.wasm!<tracing::instrument::Instrumented<T> as core::future::future::Future>::poll::h854dd9d7bd5ea7d7\n   21:  0x2dda5 - aws_sdk_rust_lambda_canary_wasm.wasm!aws_sdk_rust_lambda_canary_wasm::run_canary::{{closure}}::h5dcf7a71ecb8ab9f\n   22:  0x4c127 - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::scheduler::current_thread::Context::enter::h20b7ffba79fcbd66\n   23:  0x5114f - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::context::scoped::Scoped<T>::set::h147fdf35fc2c159a\n   24:  0x4c402 - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::scheduler::current_thread::CoreGuard::block_on::h7656a0266641155d\n   25:  0x594bc - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::context::runtime::enter_runtime::hd1a7b2f16286d49c\n   26:  0x5ad93 - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_sdk_rust_lambda_canary_wasm::Component as aws_sdk_rust_lambda_canary_wasm::exports::aws::component::canary_interface::Guest>::run_canary::ha3092741252ed2e2\n   27:  0x5611b - aws_sdk_rust_lambda_canary_wasm.wasm!aws_sdk_rust_lambda_canary_wasm::exports::aws::component::canary_interface::_export_run_canary_cabi::hf9f2e90957447e62\n   28:  0x5e1b3 - aws_sdk_rust_lambda_canary_wasm.wasm!aws:component/canary-interface#run-canary\n\nCaused by:\n    wasm trap: wasm `unreachable` instruction executed\n\nStack backtrace:\n   0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from\n   1: wasmtime::runtime::trap::from_runtime_box\n   2: wasmtime::runtime::vm::traphandlers::catch_traps\n   3: wasmtime::runtime::func::invoke_wasm_and_catch_traps\n   4: wasmtime::runtime::component::func::typed::TypedFunc<Params,Return>::call_impl\n   5: wasmtime_internal_fiber::Suspend<Resume,Yield,Return>::execute\n   6: wasmtime_internal_fiber::unix::fiber_start\n   7: wasmtime_internal_fiber::stackswitch::x86_64::wasmtime_fiber_start\n   8: wasmtime_internal_fiber::Fiber<Resume,Yield,Return>::resume\n   9: wasmtime::runtime::fiber::resume_fiber\n  10: <wasmtime::runtime::fiber::FiberFuture as core::future::future::Future>::poll\n  11: bootstrap::latest::wasm_canary::wasm_canary::{{closure}}\n  12: <tracing::instrument::Instrumented<T> as core::future::future::Future>::poll\n  13: tokio::runtime::task::core::Core<T,S>::poll\n  14: tokio::runtime::task::harness::Harness<T,S>::poll\n  15: tokio::runtime::scheduler::multi_thread::worker::Context::run_task\n  16: tokio::runtime::scheduler::multi_thread::worker::Context::run\n  17: tokio::runtime::context::scoped::Scoped<T>::set\n  18: tokio::runtime::context::runtime::enter_runtime\n  19: tokio::runtime::scheduler::multi_thread::worker::run\n  20: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll\n  21: tokio::runtime::task::core::Core<T,S>::poll\n  22: tokio::runtime::task::harness::Harness<T,S>::poll\n  23: tokio::runtime::blocking::pool::Inner::run\n  24: std::sys::backtrace::__rust_begin_short_backtrace\n  25: core::ops::function::FnOnce::call_once{{vtable.shim}}\n  26: std::sys::thread::unix::Thread::new::thread_start"},"result":"failure"}
END RequestId: f91bc1f0-f292-4b1e-aabf-d24bda74e9dc
REPORT RequestId: f91bc1f0-f292-4b1e-aabf-d24bda74e9dc	Duration: 44123.68 ms	Billed Duration: 44291 ms	Memory Size: 512 MB	Max Memory Used: 172 MB	Init Duration: 166.91 ms	

----

2026-02-25T17:52:51.867773Z ERROR wasm failed:
error while executing at wasm backtrace:
    0: 0x313462 - aws_sdk_rust_lambda_canary_wasm.wasm!abort
    1: 0x303869 - aws_sdk_rust_lambda_canary_wasm.wasm!std::sys::pal::wasip2::helpers::abort_internal::h0f2c0424e81d1365
    2: 0x2ff821 - aws_sdk_rust_lambda_canary_wasm.wasm!std::process::abort::h0feca9790f118023
    3: 0x2ff89d - aws_sdk_rust_lambda_canary_wasm.wasm!__rustc[eb8946e36839644a]::__rust_abort
    4: 0x2ff591 - aws_sdk_rust_lambda_canary_wasm.wasm!__rustc[eb8946e36839644a]::__rust_start_panic
    5: 0x2ff5b6 - aws_sdk_rust_lambda_canary_wasm.wasm!__rustc[eb8946e36839644a]::rust_panic
    6: 0x305e02 - aws_sdk_rust_lambda_canary_wasm.wasm!std::panicking::panic_with_hook::h874e3943ae58e2b0
    7: 0x3042c8 - aws_sdk_rust_lambda_canary_wasm.wasm!std::panicking::panic_handler::{{closure}}::h3336da97c87e6cc5
    8: 0x2ff9b4 - aws_sdk_rust_lambda_canary_wasm.wasm!std::sys::backtrace::__rust_end_short_backtrace::hcf057782ca878a29
    9: 0x2ff9a8 - aws_sdk_rust_lambda_canary_wasm.wasm!__rustc[eb8946e36839644a]::rust_begin_unwind
   10: 0x319c97 - aws_sdk_rust_lambda_canary_wasm.wasm!core::panicking::panic_fmt::he4af7122229aee01
   11: 0x329202 - aws_sdk_rust_lambda_canary_wasm.wasm!core::option::expect_failed::had8d4ff3f7f9fec5
   12:  0x74dd7 - aws_sdk_rust_lambda_canary_wasm.wasm!wstd::runtime::reactor::AsyncPollable::new::h76beacaa47361a09
   13:  0x6658f - aws_sdk_rust_lambda_canary_wasm.wasm!<futures_lite::future::TryZip<F1,F2> as core::future::future::Future>::poll::he1cfeb50b4cabbb9
   14:  0x670ec - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_wasm::wasi::WasiHttpConnector as aws_smithy_runtime_api::client::http::HttpConnector>::call::{{closure}}::h8ae42d3738a02b33
   15: 0x2cd32d - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime_api::client::http::HttpConnectorFuture as core::future::future::Future>::poll::h280adcdd6b23d855
   16: 0x2840dd - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::http::body::minimum_throughput::MaybeUploadThroughputCheckFuture as core::future::future::Future>::poll::h03360f94a929bb3e
   17:   0xc444 - aws_sdk_rust_lambda_canary_wasm.wasm!aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}::h826edc302a82caee
   18:  0x3ba2c - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::timeout::MaybeTimeoutFuture<InnerFuture> as core::future::future::Future>::poll::h0da7aa80ff1c4e5d
   19:  0x3e096 - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_smithy_runtime::client::timeout::MaybeTimeoutFuture<InnerFuture> as core::future::future::Future>::poll::h95b704f3404b7fbe
   20:  0x1495c - aws_sdk_rust_lambda_canary_wasm.wasm!<tracing::instrument::Instrumented<T> as core::future::future::Future>::poll::h854dd9d7bd5ea7d7
   21:  0x2dda5 - aws_sdk_rust_lambda_canary_wasm.wasm!aws_sdk_rust_lambda_canary_wasm::run_canary::{{closure}}::h5dcf7a71ecb8ab9f
   22:  0x4c127 - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::scheduler::current_thread::Context::enter::h20b7ffba79fcbd66
   23:  0x5114f - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::context::scoped::Scoped<T>::set::h147fdf35fc2c159a
   24:  0x4c402 - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::scheduler::current_thread::CoreGuard::block_on::h7656a0266641155d
   25:  0x594bc - aws_sdk_rust_lambda_canary_wasm.wasm!tokio::runtime::context::runtime::enter_runtime::hd1a7b2f16286d49c
   26:  0x5ad93 - aws_sdk_rust_lambda_canary_wasm.wasm!<aws_sdk_rust_lambda_canary_wasm::Component as aws_sdk_rust_lambda_canary_wasm::exports::aws::component::canary_interface::Guest>::run_canary::ha3092741252ed2e2
   27:  0x5611b - aws_sdk_rust_lambda_canary_wasm.wasm!aws_sdk_rust_lambda_canary_wasm::exports::aws::component::canary_interface::_export_run_canary_cabi::hf9f2e90957447e62
   28:  0x5e1b3 - aws_sdk_rust_lambda_canary_wasm.wasm!aws:component/canary-interface#run-canary

Caused by:
    wasm trap: wasm `unreachable` instruction executed

Stack backtrace:
   0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
   1: wasmtime::runtime::trap::from_runtime_box
   2: wasmtime::runtime::vm::traphandlers::catch_traps
   3: wasmtime::runtime::func::invoke_wasm_and_catch_traps
   4: wasmtime::runtime::component::func::typed::TypedFunc<Params,Return>::call_impl
   5: wasmtime_internal_fiber::Suspend<Resume,Yield,Return>::execute
   6: wasmtime_internal_fiber::unix::fiber_start
   7: wasmtime_internal_fiber::stackswitch::x86_64::wasmtime_fiber_start
   8: wasmtime_internal_fiber::Fiber<Resume,Yield,Return>::resume
   9: wasmtime::runtime::fiber::resume_fiber
  10: <wasmtime::runtime::fiber::FiberFuture as core::future::future::Future>::poll
  11: bootstrap::latest::wasm_canary::wasm_canary::{{closure}}
  12: <tracing::instrument::Instrumented<T> as core::future::future::Future>::poll
  13: tokio::runtime::task::core::Core<T,S>::poll
  14: tokio::runtime::task::harness::Harness<T,S>::poll
  15: tokio::runtime::scheduler::multi_thread::worker::Context::run_task
  16: tokio::runtime::scheduler::multi_thread::worker::Context::run
  17: tokio::runtime::context::scoped::Scoped<T>::set
  18: tokio::runtime::context::runtime::enter_runtime
  19: tokio::runtime::scheduler::multi_thread::worker::run
  20: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll
  21: tokio::runtime::task::core::Core<T,S>::poll
  22: tokio::runtime::task::harness::Harness<T,S>::poll
  23: tokio::runtime::blocking::pool::Inner::run
  24: std::sys::backtrace::__rust_begin_short_backtrace
  25: core::ops::function::FnOnce::call_once{{vtable.shim}}
  26: std::sys::thread::unix::Thread::new::thread_start

@pchickey

pchickey commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

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.

If you want to keep that current canary for testing the wasm no-os configuration, I can rename it like I did for the integration tests, and make a wasip2 canary that uses wstd natively. The source code juggling is easy enough, and I'll do my best to figure out any wiring that might need to happen to make the canary CI happen, but I expect thats where I will need your assistance.

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.)

@pchickey

pchickey commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

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:

p.hickey@KVKD0WG7VF:smithy-rs/tools]% wasmtime run -Shttp --invoke 'run-canary()' target/wasm32-wasip2/release/aws_sdk_rust_lambda_canary_wasm.wasm
ok(["authority-records/organization/organization-1.jsonl", "authority-records/organization/organization-10.jsonl", "authority-records/organization/organization-11.jsonl", "authority-records/organization/organization-12.jsonl", "authority-records/organization/organization-13.jsonl"])

@landonxjames

Copy link
Copy Markdown
Collaborator

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!

@aws-sdk-rust-ci
aws-sdk-rust-ci merged commit f401052 into smithy-lang:main Feb 27, 2026
43 of 46 checks passed
@pchickey

pchickey commented Mar 10, 2026

Copy link
Copy Markdown
Contributor Author

@landonxjames Thanks so much for your help getting this done.

I'm following up now with changes to deprecate downstream wstd-aws because its functionality is now provided by aws-smithy-wasm instead. Some things I'd like to follow up on now that the MVP is landed (and released!):

  1. The constructor WasiHttpClientBuilder::new().build() is kinda verbose. Idiomatically, impl Default for WasiHttpClient could provide the equivalent. That is a very quick and easy fix that would help users. Submitted as aws-smithy-wasm: add impl Default for WasiHttpClient #4563
  2. The rust SDK user has to depend on aws-smithy-wasm and use the items from aws_smithy_wasm::wasi directly in their aws_config::Config builder. The aws-smithy-wasm crate's readme says: "This crate is part of the AWS SDK for Rust and the smithy-rs code generator. In most cases, it should not be used directly." -- the only way to use this functionality is to go against this official advice. Should I change the README? Or should I undertake the more difficult, but perhaps more rewarding path, of making aws-config depend on the crate for target wasm32-wasip2 and provide those constructors by default, so that rust SDK users don't need to ever know/care about the existence of aws-smithy-wasm?
  3. Related, tokio is a very baked-in assumption for the default features throughout the typical aws-* crates, so anyone opting into wasm use has to use default-features = false when making any dependencies on aws-config, aws-sdk-*, otherwise e.g. there will be build errors in tokio starting with:
    error: Only features sync,macros,io-util,rt,time are supported on wasm.
       --> /Users/p.hickey/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/lib.rs:475:1
        |
    475 | compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm.");
        | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    which isn't particularly friendly for the user to diagnose as a missing default-features = false in their dep on aws-config or aws-sdk-*. Additionally, tokio is still found in a consumer project's Cargo.lock and SBOM despite not being used anywhere at runtime. Is there any appetite for an undertaking of making the tokio dep truly go away on wasm32-wasip2, or at very least for the build to not be broken-by-default with the default features?

@pchickey
pchickey deleted the wasm_use_wstd branch March 10, 2026 22:19
aws-sdk-rust-ci pushed a commit that referenced this pull request Mar 12, 2026
## Motivation and Context

Prior to this PR, the only way to construct a `WasiHttpClient` is via
`WasiHttpClientBuilder::new().build()`. There are no other options on
the Builder. The Builder exists to provide a surface for future
expansion, and because #4498 was designed to minimize diff when changing
the implementation behind the WasiHttpClient type.

## Description

Adds `impl Default for WasiHttpClient` containing the trivial
construction.

## Testing
The existing test in `tools/ci-cdk/canary-wasm` has been modified to
exercise this new constructor.


## Checklist
<!--- If a checkbox below is not applicable, then please DELETE it
rather than leaving it unchecked -->
- [ ] For changes to the smithy-rs codegen or runtime crates, I have
created a changelog entry Markdown file in the `.changelog` directory,
specifying "client," "server," or both in the `applies_to` key.
- [ ] For changes to the AWS SDK, generated SDK code, or SDK runtime
crates, I have created a changelog entry Markdown file in the
`.changelog` directory, specifying "aws-sdk-rust" in the `applies_to`
key.

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._

---------

Co-authored-by: ysaito1001 <awsaito@amazon.com>
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.

3 participants