Stream: wasi

Topic: WASIP3 Update


view this post on Zulip Bailey Hayes (Jan 15 2025 at 16:20):

Late last year we decided that we'd like to start running a standup style update and to use the Ship WASIp3 project board (see topic #wasi > WASIp3 project board @ 💬 for background) to coordinate work.

Let's kick things off with an async style standup for this week!

Ship WASIp3

view this post on Zulip Bailey Hayes (Jan 15 2025 at 16:22):

Folks that have active work streams, will you post a quick update?
cc @Victor Adossi @Roman Volosatovs @Joel Dice

view this post on Zulip Bailey Hayes (Jan 15 2025 at 16:32):

Jan 15, 2025

Bailey Hayes: WASI clocks and random 0.3.0-draft WIT definitions have been reviewed and merged. We adjusted the API for wasi-clocks now that fn's are async, see: https://github.com/WebAssembly/wasi-clocks/blob/main/wit-0.3.0-draft/monotonic-clock.wit#L34-L44

We decided to rev the since versions as 0.3.0 will make breaking changes to the 0.2.x series. Expect all 0.3.0-draft WIT's to align to this. Once @Roman Volosatovs PR's for filesystem and sockets merge, wasi-cli is the next target. I believe we're very close to having a draft for WASIP2 interfaces (http draft already exists but will be updated once deps land).

Once the above is complete, adding support for WASIP3 interfaces in wasmtime and JCO can begin

Clocks API for WASI. Contribute to WebAssembly/wasi-clocks development by creating an account on GitHub.
Ship WASIp3

view this post on Zulip Bailey Hayes (Jan 15 2025 at 16:40):

Items Ready for Work

If you're interested in jumping in, I see a couple items that could begin now:

When picking up a new issue on the board, set yourself as the assignee.

Ship WASIp3
Ship WASIp3

view this post on Zulip Joel Dice (Jan 15 2025 at 16:41):

Async/future/stream/error-context support has been merged into wasm-tools and wit-bindgen and is available in their latest releases. Still iterating on the Wasmtime PR, knocking out todo items one by one. Hoping to move that one to "ready-for-review" by the end of the month. Meanwhile, it is feature-complete (modulo the error-context work Victor is doing, which I'm reviewing now), so feel free to clone the branch, kick the tires, and start adding WASIp3 support to wasmtime-wasi and wasmtime-wasi-http.

view this post on Zulip Victor Adossi (Jan 15 2025 at 16:41):

Hey all, here's what I'm working on right now:

CC @Calvin Prewitt who is doing the actual bulk of the work of jco host async imports

view this post on Zulip Roman Volosatovs (Jan 16 2025 at 14:50):

wasi-sockets and wasi-filesystem WIT update PRs are ready for review

will work on removing wasi:io/error.error dep from wasi:http and after that start WASI implementation in Wasmtime

view this post on Zulip Dave Bakker (badeend) (Jan 16 2025 at 14:52):

Thanks. I've got a few remarks on the wasi-sockets part. Hope to get it written down soon

view this post on Zulip Pat Hickey (Jan 16 2025 at 16:05):

What’s the status of implementing P3 streams and futures in wasmtime::component? That’s a prerequisite to a wasi impl, correct?

view this post on Zulip Joel Dice (Jan 16 2025 at 16:14):

@Pat Hickey see my update above; that's feature-complete and has decent test coverage. Working to get that PR in a reviewable state (hopefully in the next week or two), but meanwhile you can use my PR branch.

view this post on Zulip Pat Hickey (Jan 16 2025 at 16:28):

Thanks. I will take a look. I’ve been factoring out wasi-io from wasmtime-wasi so that at least that much can be built nostd, idk how that will intersect with these new streams and futures but hopefully they can plug together

view this post on Zulip Roman Volosatovs (Jan 17 2025 at 11:59):

Just a heads-up, I've started working on stream types with no <T>, added this ticket to the board: https://github.com/orgs/bytecodealliance/projects/16?pane=issue&itemId=94157967
i.e. implementing the spec change from https://github.com/WebAssembly/component-model/pull/440 in wasm-tools and wit-bindgen

Ship WASIp3
For the same reason that variant and result case payloads and func results are optional, it seems like the element types of future and stream should be optional, allowing them to convey (single-sho...

view this post on Zulip Roman Volosatovs (Jan 17 2025 at 12:01):

Opened a draft PR to wasi:cli for 0.3.0 https://github.com/WebAssembly/wasi-cli/pull/52
a few smaller-scoped wasi:http updates to 0.3.0 https://github.com/WebAssembly/wasi-http/pull/143 https://github.com/WebAssembly/wasi-http/pull/142
wasi:random fix https://github.com/WebAssembly/wasi-random/pull/52

Refs WebAssembly/wasi-random#52 Refs WebAssembly/wasi-sockets#111 Refs WebAssembly/wasi-filesystem#164
Remove wasi:io usage in wit-0.3.0-draft Followed the same stream error handling convention as currently in feat: add wasi-0.3.0 draft wasi-filesystem#164 feat: add wasi-0.3.0 draft wasi-sockets#111
update wit-deps to 0.5.0 (mainly for feat: add support for subdir bytecodealliance/wit-deps#254) verify wit-0.3.0-draft deps in CI update wasi:clocks in wit-0.3.0-draft subtree to 0.3.0 remove redu...
Refs WebAssembly/wasi-filesystem#164 (comment)

view this post on Zulip Roman Volosatovs (Jan 17 2025 at 12:50):

Added a draft PR for stream of unit: https://github.com/bytecodealliance/wasm-tools/pull/1978

Add support for streams with no elements (streams of unit) Refs WebAssembly/component-model#440

view this post on Zulip Roman Volosatovs (Jan 21 2025 at 15:05):

started the wasmtime WASI 0.3 impl https://github.com/bytecodealliance/wasmtime/pull/10061

This adds support for wasi:random@0.3.0 from https://github.com/WebAssembly/wasi-random/tree/3e99124e81d0f80872b826d161bef077ee37d241/wit-0.3.0-draft The change is fully backwards-compatible from t...

view this post on Zulip Roman Volosatovs (Jan 21 2025 at 16:47):

and now with actual async: https://github.com/bytecodealliance/wasmtime/pull/10063/commits/171a532910790379ebbfd85ddbb62b6f60a1fbff

component build fails with:

  thread 'main' panicked at crates/test-programs/artifacts/build.rs:176:10:
  module can be translated to a component: failed to validate component output

  Caused by:
      canonical option `async` requires the component model async feature (at offset 0x82da1a)

Will try basing on async branch

btw, I've noticed that wit-bindgen-rt dependency, which appears to be used by async is missing out-of-the-box.
I believe deps are normally reexported by wit-bindgen, but in this case it appears that macro attempts to import from ::wit-bindgen-rt
cc @Joel Dice idk, if that's a known/fixed issue or do you want me to take a look?

Add support for wasi:clocks@0.3.0. Blocked on #10061

view this post on Zulip Roman Volosatovs (Jan 21 2025 at 16:59):

filed https://github.com/bytecodealliance/wit-bindgen/issues/1135, working on a fix

Currently wit-bindgen explicitly imports ::wit_bindgen_rt for async, e.g.: wit-bindgen/crates/rust/src/lib.rs Lines 458 to 526 in 629ced7 if !self.future_payloads.is_empty() { self.src.push_str( "\...

view this post on Zulip Roman Volosatovs (Jan 21 2025 at 17:35):

this seems to have fixed the issue: https://github.com/bytecodealliance/wit-bindgen/pull/1136

Closes #1135

view this post on Zulip Joel Dice (Jan 21 2025 at 23:43):

FYI, I'm starting to work on wit-bindgen C support for async/streams/futures, which will unblock wasip3 support in wasi-libc and the toolchains which depend on it.

view this post on Zulip Roman Volosatovs (Jan 22 2025 at 13:31):

I've rebased my Wasmtime WASI changes on latest async from @Joel Dice in https://github.com/rvolosatovs/wasmtime/tree/async-wasi

wasi:clocks@0.3.0 test fails for now, but looks like we're pretty close to getting this working end-to-end:

on https://github.com/rvolosatovs/wasmtime/commit/8ea812e04a77ab7a396bd74876d8c8ef6f0b017b

---- async_::preview3_sleep stdout ----
preopen: TempDir { path: "/var/folders/bq/thy1_b7x29l7s2wqw39r62yw0000gn/T/wasi_components_preview3_sleep.component_cp7fbR" }
thread 'async_::preview3_sleep' panicked at /Users/rvolosatovs/src/github.com/bytecodealliance/wasmtime/crates/wasi/src/runtime.rs:108:15:
Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- sync::preview3_sleep stdout ----
preopen: TempDir { path: "/var/folders/bq/thy1_b7x29l7s2wqw39r62yw0000gn/T/wasi_components_preview3_sleep.component_bQriUp" }
thread 'sync::preview3_sleep' panicked at /Users/rvolosatovs/src/github.com/bytecodealliance/wasmtime/crates/wasmtime/src/runtime/component/concurrent.rs:534:54:
called `Option::unwrap()` on a `None` value


failures:
    async_::preview3_sleep
    sync::preview3_sleep

I'll start digging :)

Standalone JIT-style runtime for WebAssembly, using Cranelift - GitHub - rvolosatovs/wasmtime at async-wasi
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

view this post on Zulip Roman Volosatovs (Jan 22 2025 at 18:44):

I got wasi:clocks@0.3.0 test passing with async runtime in https://github.com/rvolosatovs/wasmtime/commit/c3406b2cb02a6013add16867a8c6debad8bbef39
thanks @Joel Dice for the help!

I noticed the same "current task missing" panic when attempting to run the same test with async_support(false), i.e. using sync host bindings. It makes sense, since in that case none of the async machinery seem to be used
What is the current thinking around that - are we planning to support wasip3 on hosts without async_support at all?

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

view this post on Zulip Joel Dice (Jan 22 2025 at 18:48):

@Alex Crichton and I discussed this a while ago. We don't think WASIp3 or the component model async ABI make sense to support in Wasmtime with async_support(false), and we're actually considering deprecating Wasmtime's component model sync APIs (i.e. making async_support(true) the default and, eventually, only option for running components).

view this post on Zulip Roman Volosatovs (Jan 22 2025 at 18:50):

That sounds good to me and simplifies this effort - I won't be adding the sync bindings to wasip3 interfaces at all then :)

view this post on Zulip Pat Hickey (Jan 22 2025 at 18:53):

thanks Joel, that sounds right - we'll have to see about deprecating the sync stuff for p2 we already provide (hacky as it is, it does actually meet some users needs) but I agree we shouldn't worry about sync interfaces to p3 or async CM

view this post on Zulip Juniper Tyree (Jan 23 2025 at 06:42):

Do I understand correctly that the plan is that the CM host must support async, but that all components can still be fully sync (if one wants that)? If wasmtime will always use async, it may be useful to support compiling with a very cheap async runtime so that e.g. embedded usecases don’t need to pull in a costly featureful runtime

view this post on Zulip Pat Hickey (Jan 23 2025 at 18:03):

Yes, you should basically just need tasks (which can be implemented with a library e.g. https://docs.rs/futures/latest/futures/task/index.html), and whatever your platform needs for IO to make a custom executor

view this post on Zulip Pat Hickey (Jan 23 2025 at 18:04):

I'm working on exactly that for P2 right now, the need is not limited to P3

view this post on Zulip Pat Hickey (Jan 23 2025 at 18:04):

the existing P2 wasmtime-wasi always runs inside tokio, with the sync bindings it just hides that tokio in the background.

view this post on Zulip Roman Volosatovs (Jan 30 2025 at 18:06):

@Pat Hickey @Joel Dice @Alex Crichton @Victor Adossi I've sent you all invites to a 30 min call tomorrow, please let me know if that time slot does not work for you.
If it does, then first item on the agenda would be discussing time slots and making this a regular meeting :)

view this post on Zulip Roman Volosatovs (Jan 30 2025 at 18:07):

(I used emails from Wasmtime git log mostly)

view this post on Zulip Roman Volosatovs (Jan 30 2025 at 18:45):

just realized I scheduled the meeting for next week :thinking: , just rescheduled for tomorrow, also moved it to a bit later to accommodate for US West Coast

view this post on Zulip Alex Crichton (Jan 30 2025 at 21:51):

works for me yeah :+1:

view this post on Zulip Alex Crichton (Jan 31 2025 at 18:35):

joel/I won't be around next monday but don't let my absence block y'all the monday after that from meeting

view this post on Zulip Alex Crichton (Jan 31 2025 at 18:37):

I've created https://github.com/bytecodealliance/wasip3-prototyping and we should all have admin access there

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Alex Crichton (Jan 31 2025 at 18:38):

I avoided a literal fork b/c i don't think github lets you fork a repo within the same org

view this post on Zulip Alex Crichton (Jan 31 2025 at 18:38):

just pushed up wasmtime's current main to the main there as well

view this post on Zulip Roman Volosatovs (Feb 01 2025 at 09:13):

Small follow-up to the discussion from yesterday, just for the sake of completeness - without any changes to the wasmtime bindgen, we should be able to use dynamic dispatch to avoid the complex state machines in implementations. I haven't tested it, but I don't see why returning a Box<dyn FnOnce(..)> wouldn't work.

It's essentially the same thing we've been doing for a long time with async_trait, but it does seem as a bit of a setback, since we'd not be able to "just" use Rust async. It also seems non-obvious for embedders, especially those not completely familiar with dynamic dispatch/async (e.g. explicit Box<dyn ..> bounds would likely be required to avoid compiler errors)

Just throwing it out there as a potential solution, I believe having "true" Rust async trait support would be a lot nicer/better

view this post on Zulip Joel Dice (Feb 02 2025 at 22:26):

Can you clarify how returning a Box<dyn ...> would help? I'm not seeing what part of the problem it solves.

view this post on Zulip Joel Dice (Feb 02 2025 at 22:28):

FWIW, I just sketched out a potential API based on a thread-local variable which is only set to a valid value when Wasmtime is polling futures created by functions registered using LinkerInstance::func_wrap_concurrent: https://gist.github.com/dicej/21519f9cf2e4d57a3316ea0b2167d281

Sketch of alternative `wasmtime-wit-bindgen` `concurrent-imports` approach based on thread-local storage - concurrent-bindgen-sketch.rs

view this post on Zulip Roman Volosatovs (Feb 03 2025 at 14:06):

diff --git a/crates/wasi/src/p3/sockets/host/types/tcp.rs b/crates/wasi/src/p3/sockets/host/types/tcp.rs
index e2a45eb6c..c5f3cbb7f 100644
--- a/crates/wasi/src/p3/sockets/host/types/tcp.rs
+++ b/crates/wasi/src/p3/sockets/host/types/tcp.rs
@@ -45,64 +45,65 @@ where
         let ctx = store.data().sockets();
         let allowed = ctx.allowed_network_uses.tcp;
         let socket_addr_check = ctx.socket_addr_check.clone();
-        let sock = store
+        let tcp_socket = match store
             .data_mut()
             .table()
             .get_mut(&mut socket)
             .context("failed to get socket resource from table")
-            .map(|socket| {
-                let tcp_state = mem::replace(&mut socket.tcp_state, TcpState::BindStarted);
-                if let TcpState::Default(sock) = tcp_state {
-                    Some((sock, socket.family))
-                } else {
-                    socket.tcp_state = tcp_state;
-                    None
-                }
+        {
+            Ok(sock) => sock,
+            Err(err) => {
+                return Box::pin(async move {
+                    for_any(Box::new(for_any(move |_| Err(err)))) as Box<dyn FnOnce(_) -> _>
+                }) as Pin<Box<dyn Future<Output = _>>>
+            }
+        };
+        let tcp_state = mem::replace(&mut tcp_socket.tcp_state, TcpState::BindStarted);
+        let sock = if let TcpState::Default(sock) = tcp_state {
+            sock
+        } else {
+            tcp_socket.tcp_state = tcp_state;
+            return Box::pin(async {
+                for_any(
+                    Box::new(move |_| Ok(Err(ErrorCode::InvalidState))) as Box<dyn FnOnce(_) -> _>
+                )
             });
+        };
         let local_address = SocketAddr::from(local_address);
-        async move {
-            let res = match sock {
-                Ok(sock)
-                    if !allowed
-                        || !socket_addr_check(local_address, SocketAddrUse::TcpBind).await =>
-                {
-                    if let Some((sock, ..)) = sock {
-                        Ok(Ok((sock, Err(ErrorCode::AccessDenied))))
-                    } else {
-                        Ok(Err(ErrorCode::AccessDenied))
-                    }
-                }
-                Ok(Some((sock, family))) => {
-                    let res = bind(&sock, local_address, family);
-                    Ok(Ok((sock, res)))
-                }
-                Ok(None) => Ok(Err(ErrorCode::InvalidState)),
-                Err(err) => Err(err),
-            };
-            for_any(move |mut store: StoreContextMut<'_, Self::TcpSocketData>| {
-                let sock = res?;
-                let socket = store
+        Box::pin(async move {
+            if !allowed || !socket_addr_check(local_address, SocketAddrUse::TcpBind).await {
+                return Box::new(move |mut store: StoreContextMut<'_, Self::TcpSocketData>| {
+                    let tcp_socket = store
+                        .data_mut()
+                        .table()
+                        .get_mut(&mut socket)
+                        .context("failed to get socket resource from table")?;
+                    tcp_socket.tcp_state = TcpState::Default(sock);
+                    Ok(Err(ErrorCode::AccessDenied))
+                }) as Box<dyn FnOnce(_) -> _>;
+            }
+            Box::new(move |mut store: StoreContextMut<'_, Self::TcpSocketData>| {
+                let tcp_socket = store
                     .data_mut()
                     .table()
                     .get_mut(&mut socket)
                     .context("failed to get socket resource from table")?;
-                let (sock, res) = match sock {
-                    Ok(sock) => sock,
-                    Err(err) => return Ok(Err(err)),
-                };
                 ensure!(
-                    matches!(socket.tcp_state, TcpState::BindStarted),
+                    matches!(tcp_socket.tcp_state, TcpState::BindStarted),
                     "corrupted socket state"
                 );
-                if let Err(err) = res {
-                    socket.tcp_state = TcpState::Default(sock);
-                    Ok(Err(err))
-                } else {
-                    socket.tcp_state = TcpState::Bound(sock);
-                    Ok(Ok(()))
+                match bind(&sock, local_address, tcp_socket.family) {
+                    Ok(()) => {
+                        tcp_socket.tcp_state = TcpState::Bound(sock);
+                        Ok(Ok(()))
+                    }
+                    Err(err) => {
+                        tcp_socket.tcp_state = TcpState::Default(sock);
+                        Ok(Err(err))
+                    }
                 }
             })
-        }
+        })
     }

     fn connect(

something roughly like this. I did not play the lifetime bingo to solve the "one type is more general than the other" and "implementation of FnOnce is not general enough", but that's a potential workaround (which, it seems, would require even more helpers akin to for_any). I'm not sure if it's more ergonomic or clear.

Your sketch looks good to me, however, and I think it makes a lot of sense.

view this post on Zulip Joel Dice (Feb 04 2025 at 13:59):

FYI, I just pushed my async branch to the main branch of the wasip3-prototyping repo. I won't rebase it anymore after that; we can merge from upstream main as necessary, which should be less disruptive than rebasing.

view this post on Zulip Pat Hickey (Feb 05 2025 at 17:35):

I missed wherever this came up on github - whats the reasoning behind dropping the -draft suffix on wasi 0.3 wit packages versions?

view this post on Zulip Roman Volosatovs (Feb 05 2025 at 18:14):

https://github.com/WebAssembly/wasi-filesystem/pull/164/commits/44b42cdf648e32482a7167ed182265be9623a7c3

Refs https://github.com/orgs/bytecodealliance/projects/16/views/1?pane=issue&itemId=88153596 Refs WebAssembly/wasi-sockets#111 Refs #156 (change sets seem to be complimentary) Followed the exam...

view this post on Zulip Roman Volosatovs (Feb 05 2025 at 18:15):

Looks like I've discovered, what appears to be, a bindgen bug https://github.com/bytecodealliance/wasip3-prototyping/issues/2, but not entirely sure yet.

This appears to be bindgen bug, but not entirely sure that's the case. On d8c91c3 (from #1 ) with the following patch applied: diff --git a/crates/wasi/tests/all/p3/sockets.rs b/crates/wasi/tests/a...

view this post on Zulip Pat Hickey (Feb 05 2025 at 18:40):

ok got it. so we can restore the -draft once that bug is fixed?

view this post on Zulip Roman Volosatovs (Feb 05 2025 at 18:56):

I think so, however is there a particular reason we'd want the -draft suffix?
Since the interfaces are in a separate (draft) directory within proposal repositories anyway, the fact that those interfaces are "draft" should be clear and not introducing the suffix seem to minimize the churn

view this post on Zulip Bailey Hayes (Feb 05 2025 at 19:14):

It's a precedent we set with wasip2. We don't want anyone to accidentally think wasi 0.3.0 is ready. We're also expecting to make a series of updates as these are unlikely to be the final versions of the interfaces. -draft makes that easier.

view this post on Zulip Pat Hickey (Feb 05 2025 at 22:01):

yep. we have meaningful semver there, so lets use it.

view this post on Zulip Pat Hickey (Feb 05 2025 at 22:01):

it also means we can publish the draft versions to an OCI registry fearlessly.

view this post on Zulip Victor Adossi (Feb 10 2025 at 17:14):

Some fast-feedback would be great on this issue in wasi-http:

https://github.com/WebAssembly/wasi-http/issues/153

It looks like a signature (body.finish) needs to change given that internally it produces an error-context. There are many options for how to fix it, but it would be great to get that fix in upstream on the 0.3.0-draft

During some implementation for error-contexts in futures in the wasip3-prototyping repo, we found that there was an issue with wasi:http/types#body.finish, as it implicitly does a future.read which...

view this post on Zulip Roman Volosatovs (Feb 10 2025 at 17:30):

A quick summary of the status meeting earlier today, please let me know if I missed something:

view this post on Zulip Joel Dice (Feb 10 2025 at 20:02):

@Roman Volosatovs this fixes the borrow issue: https://github.com/bytecodealliance/wasip3-prototyping/pull/4

view this post on Zulip Roman Volosatovs (Feb 11 2025 at 10:58):

Awesome, thanks @Joel Dice ! Just tested it and can confirm that it fixed the issue I've encountered :)

view this post on Zulip Joel Dice (Feb 12 2025 at 01:33):

Here's the wasmtime-wit-bindgen ergonomics refactor: https://github.com/bytecodealliance/wasip3-prototyping/pull/6

I had a few goals with this PR: Improve the ergonomics of concurrent import bindings by supporting async/await sugar and allowing store access to be arbitrarily interspersed between await points ...

view this post on Zulip Roman Volosatovs (Feb 12 2025 at 15:40):

Looks great! Here's bind and connect with new API https://github.com/bytecodealliance/wasip3-prototyping/blob/7dbc8a9fd6a2348e772a32382c3e29c88cad397e/crates/wasi/src/p3/sockets/host/types/tcp.rs#L67-L153

See also https://github.com/bytecodealliance/wasip3-prototyping/pull/6#pullrequestreview-2612364221

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping
I had a few goals with this PR: Improve the ergonomics of concurrent import bindings by supporting async/await sugar and allowing store access to be arbitrarily interspersed between await points ...

view this post on Zulip Roman Volosatovs (Feb 12 2025 at 19:12):

first, quick, incomplete attempt at TCP send looks roughly like that https://github.com/bytecodealliance/wasip3-prototyping/blob/e84bce870bf7bafed014b0a536445e1e0deb22fa/crates/wasi/src/p3/sockets/host/types/tcp.rs#L263-L366
once I can get listen working, I'll be able to run some tests

(this also lacks shutdown on EOF, but just testing out the API for now)

view this post on Zulip Joel Dice (Feb 12 2025 at 22:38):

@Roman Volosatovs this should unblock listen: https://github.com/bytecodealliance/wasip3-prototyping/pull/8

view this post on Zulip Roman Volosatovs (Feb 13 2025 at 16:42):

Thanks @Joel Dice !
Working on listen I'm getting a sefault with this API and I've also ran into the failed to get promise due to cannot remove owned resource while borrowed again, looks like there's indeed a bug, which is likely similar to what happened with borrows.

I've also added a little commit to allow spawn on store directly (from within with) (https://github.com/bytecodealliance/wasip3-prototyping/pull/1/commits/e4e4e5531aee37c0a99ea5e2d9364c30c001752d), however even after reverting that I'm still getting the same result.

What's the most efficient way to proceed here?
Should I file issues with reproduction steps?
Would it help to get on a call and pair?

I've pushed my commit trace to https://github.com/bytecodealliance/wasip3-prototyping/pull/1

view this post on Zulip Joel Dice (Feb 13 2025 at 16:46):

Filing issues would be ideal. They don't need detailed descriptions -- just brief descriptions of each issue with steps to repro.

view this post on Zulip Joel Dice (Feb 13 2025 at 16:49):

BTW, I've been wondering how listen: func() -> result<stream<tcp-socket>, error-code> is supposed to work given that the tcp-socketborrow only lasts until listen returns, i.e. the callee no longer has access to it after returning, so it can't use it in the spawned task. Curious if @Luke Wagner has guidance on this.

view this post on Zulip Roman Volosatovs (Feb 13 2025 at 17:05):

@Joel Dice https://github.com/bytecodealliance/wasip3-prototyping/pull/1/commits/c347376e66784b1a3560f3a5efb537961452832a

Refs WebAssembly/wasi-cli#52 Refs bytecodealliance/wasmtime#10063 Refs bytecodealliance/wasmtime#10061 Refs bytecodealliance/wasmtime#10073

view this post on Zulip Roman Volosatovs (Feb 13 2025 at 17:16):

filed the issue at https://github.com/bytecodealliance/wasip3-prototyping/issues/9

Using Accessor::spawn from e6179b6 (#8), I'm getting a segfault on c347376 A way to reproduce this error is: cargo test -p wasmtime-wasi p3 -- --ignored --nocapture test p3::sockets::sockets_0_3_tc...

view this post on Zulip Joel Dice (Feb 13 2025 at 17:49):

BTW, I've been wondering how listen: func() -> result<stream<tcp-socket>, error-code> is supposed to work given that the tcp-socketborrow only lasts until listen returns, i.e. the callee no longer has access to it after returning, so it can't use it in the spawned task.

Roman and I discussed this in today's Wasmtime meeting and he clarified that the host implementation of listen does not attempt to use the borrowed resource as such after the function returns -- instead it clones the backing implementation and uses that, which makes sense. And I guess a component-implemented version could do the same thing by making the exported tcp-socketresource implementation contain a cloneable and interior-ly mutable state which may be cloned for post-return use.

view this post on Zulip Roman Volosatovs (Feb 13 2025 at 17:54):

Filed an issue for the second error I've encountered: https://github.com/bytecodealliance/wasip3-prototyping/issues/10

This issue looks very similar to #2, encountered while implementing wasi:sockets TCP On c347376 apply: diff --git a/crates/wasi/tests/all/p3/sockets.rs b/crates/wasi/tests/all/p3/sockets.rs index 3...

view this post on Zulip Joel Dice (Feb 13 2025 at 18:30):

@Roman Volosatovs The segfault you found is the same as the one I discovered last week in the context of epoch interruption (although it turns out it can happen even with epoch interruption disabled) and am in the process of addressing. Meanwhile, this tiny PR makes it panic instead of segfault.

view this post on Zulip Roman Volosatovs (Feb 13 2025 at 18:48):

Awesome, thanks for looking into it. Can confirm that it does not segfault anymore! :)

view this post on Zulip Joel Dice (Feb 13 2025 at 22:38):

@Roman Volosatovs This fixes issue #10: https://github.com/bytecodealliance/wasip3-prototyping/pull/12. I'll continue working on #9, but might not finish it before the end of my day, in which case I should have a PR up tomorrow.

view this post on Zulip Victor Adossi (Feb 14 2025 at 03:03):

Do we want to get CI running on the prototyping repo? I must have missed the how/when/why of when it was disabled, but having some tests run at PR time is likely better than none.

It's not a showstopper as I think a forking workflow would allow all the changes anyone wanted, but just bringing it up here for discussion.

view this post on Zulip Joel Dice (Feb 14 2025 at 04:16):

Yes, that would be great.

view this post on Zulip Joel Dice (Feb 14 2025 at 21:54):

@Roman Volosatovs This PR addresses #9. BTW, I merged my other outstanding PRs (despite not yet being approved) because juggling 4 different branches was irritating me. I'd also like to merge yours as soon as it's somewhat stable (#[ignoreing tests as necessary) so we don't need to jump back and forth so much.

view this post on Zulip Joel Dice (Feb 14 2025 at 21:57):

With that PR, the tests that were failing due to #9 no longer panic, but they hang indefinitely, consuming no CPU. Not sure if that's a bug in the tests or in Wasmtime; I haven't had a chance to study them yet.

view this post on Zulip Joel Dice (Feb 14 2025 at 22:00):

I general, I think we can be pretty aggressive about merging PRs for now and avoid long-lived branches. We're going to split it all up again for upstreaming anyway; for now let's keep things simple. Enabling CI as Victor suggested will help avoid stepping on each others' toes.

view this post on Zulip Roman Volosatovs (Feb 19 2025 at 13:01):

Sounds good, I've rebased https://github.com/bytecodealliance/wasip3-prototyping/pull/1 on latest main and marked it ready for review.
Unfortunately, I was not able to enable all TCP tests yet, as it seems I'm hitting a deadlock with stream I/O, the host never receives the data that the guest sends. I'll file an issue later today

Refs WebAssembly/wasi-cli#52 Refs bytecodealliance/wasmtime#10063 Refs bytecodealliance/wasmtime#10061 Refs bytecodealliance/wasmtime#10073 This currently contains fully implemented and tested wasi...

view this post on Zulip Joel Dice (Feb 19 2025 at 14:23):

Yeah, that deadlock sounds like the hang I saw last week. I can look into that today. If you can minimize the test case that reproduces it at all, that would definitely help.

view this post on Zulip Roman Volosatovs (Feb 19 2025 at 15:26):

I tracked it down to these two:
guest: https://github.com/bytecodealliance/wasip3-prototyping/blob/33263c939f09ec0c68d200b7b8048441812657d4/crates/test-programs/src/bin/sockets_0_3_tcp_bind.rs#L71
host: https://github.com/bytecodealliance/wasip3-prototyping/blob/33263c939f09ec0c68d200b7b8048441812657d4/crates/wasi/src/p3/sockets/host/types/tcp.rs#L435

Neither of these calls ever resolve, as if the futures are not polled
I'm using the Promise::into_future in the host, which seems to be the right thing to do according to the docs, I have not tried it with Promise::get

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping
Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Joel Dice (Feb 19 2025 at 15:27):

Yeah, Promise::into_future is the only one that makes sense in this context. I'll take a look.

view this post on Zulip Joel Dice (Feb 19 2025 at 18:40):

Based on println debugging the guest is not even reaching the line you linked to. Since the guest has lowered thetcp-socket.send import synchronously, and the implementation is trying to read the entire stream<u8> before returning, there's no way it will ever return; the guest is blocked on that call and will never write anything to the stream.

I think you'll want to lower the tcp-socket.send import asynchronously and await it concurrently with a future that feeds the write end of the stream (e.g. using join or FuturesUnordered). Happy to pair on this when you're available.

view this post on Zulip Roman Volosatovs (Feb 19 2025 at 19:59):

Right, yeah, that makes sense, thanks!

view this post on Zulip Roman Volosatovs (Feb 19 2025 at 19:59):

I'll push a fix later tonight if I'll get a chance, tomorrow otherwise

view this post on Zulip Roman Volosatovs (Feb 19 2025 at 20:53):

had a few minutes to try it out https://github.com/bytecodealliance/wasip3-prototyping/pull/17, will need to figure out a way to properly adapt the wasip2 test expectations regarding the behavior, but looks like it works. tcp_streams still hangs, but that's likely due to some write handle not being dropped. Will continue tomorrow.
Thanks for taking a look, looks like we'll be able to have the complete TCP test suite working tomorrow

We read every piece of feedback, and take your input very seriously.

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 11:15):

Interesting, looks like I found another issue - the BackgroundTask is not awoken by the executor after returning Poll::Pending.
I think it would be beneficial to pair later today!

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 11:18):

if this is the waker used to poll these tasks, it would explain what I'm seeing: https://github.com/bytecodealliance/wasip3-prototyping/blob/f5fefc6f4e63b311850421c75d5cdb2e96784a7c/crates/wasmtime/src/runtime/component/concurrent.rs#L1459-L1469
https://github.com/bytecodealliance/wasip3-prototyping/blob/f5fefc6f4e63b311850421c75d5cdb2e96784a7c/crates/wasmtime/src/runtime/component/concurrent.rs#L1561

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping
Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 11:22):

specifically, this future never gets polled again after returning Poll::Pending, even though oneshot::Receiver poll should have registered the wakup event once the oneshot::Sender is dropped (I have verified that it indeed gets dropped) https://docs.rs/tokio/latest/tokio/sync/oneshot/struct.Receiver.html

https://github.com/bytecodealliance/wasip3-prototyping/blob/f5fefc6f4e63b311850421c75d5cdb2e96784a7c/crates/wasi/src/p3/sockets/host/types/tcp.rs#L121-L125

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Joel Dice (Feb 20 2025 at 14:44):

@Roman Volosatovs dummy_waker is only used in first_poll and poll_and_block, and those are only used for guest->host calls in host.rs, meaning dummy_waker should never be used for spawned tasks. Instead, spawned tasks are pushed directly to ConcurentState::futures, and that is always polled with the Context received from the embedder's executor (i.e. Tokio in this case).

My guess is that we're not polling ConcurrentState::futures between when spawn is called and when we suspend the fiber and return control to the executor, i.e. the spawned future is not being polled at all. Or have you already verified that it's being polled at least once?

Happy to pair today when you're available. Meanwhile, I'll take a closer look.

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 14:59):

It gets polled once for sure. I'll be available in a few minutes, we could jump on a call if you're free

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 15:06):

https://meet.google.com/sta-snii-ffj

view this post on Zulip Joel Dice (Feb 20 2025 at 15:46):

Ok, after looking at the code, I think you're right that the issue is related to the guest synchronously dropping the listening tcp socket, which in the host drops the oneshot::Sender, but the guest code keeps running after the drop call returns, before the host has a chance to poll ConcurrentState::futures again.

view this post on Zulip Joel Dice (Feb 20 2025 at 15:47):

So we get the trap because the guest tries to bind again before the old socket has really stopped listening.

view this post on Zulip Joel Dice (Feb 20 2025 at 15:48):

I'm wondering if there's a way we can make HostTcpSocket::drop finish everything it needs to do (including waiting for the spawned future to complete) before returning.

view this post on Zulip Joel Dice (Feb 20 2025 at 15:50):

It's like the spawned future needs to send a confirmation back to HostTcpSocket::drop indicating it's done.

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 15:50):

For my understanding then, are you saying the observed behavior is a race condition effectively?

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 15:51):

Would the future eventually get polled on it's own or it does require something to trigger the poll?

view this post on Zulip Joel Dice (Feb 20 2025 at 15:51):

Kind of, except that it's 100% deterministic.

view this post on Zulip Joel Dice (Feb 20 2025 at 15:51):

yes, I think the future would be polled if the guest were to yield between the drop and the bind

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 15:52):

Want to jump back on the call to chat for a bit?

view this post on Zulip Joel Dice (Feb 20 2025 at 15:52):

or if (like I was saying), the host drop implementation were to wait for confirmation before returning

view this post on Zulip Joel Dice (Feb 20 2025 at 15:52):

yup

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 15:52):

https://meet.google.com/sta-snii-ffj

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 16:10):

actually, following-up to our discussion just now, I might try taking the task out from the drop directly, by wrapping the ListenTask itself

It does seem like a generally useful pattern, but I'm not actually sure if the abort handle should be responsibility of the runtime if we can figure that out by wrapping the task directly

view this post on Zulip Joel Dice (Feb 20 2025 at 16:11):

Makes sense; want to try that before I start messing with the runtime code?

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 16:12):

sounds good, let me try a few things!

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 16:37):

diff --git a/crates/wasi/src/p3/sockets/host/types/tcp.rs b/crates/wasi/src/p3/sockets/host/types/tcp.rs
index d2b43129b..db000c471 100644
--- a/crates/wasi/src/p3/sockets/host/types/tcp.rs
+++ b/crates/wasi/src/p3/sockets/host/types/tcp.rs
@@ -4,8 +4,8 @@ use core::net::SocketAddr;
 use core::pin::{pin, Pin};
 use core::task::Poll;

-use std::net::Shutdown;
 use std::sync::Arc;
+use std::{net::Shutdown, os::fd::AsRawFd as _};

 use anyhow::{ensure, Context as _};
 use io_lifetimes::AsSocketlike as _;
@@ -769,7 +769,8 @@ where
             .delete(rep)
             .context("failed to delete socket resource from table")?;
         match sock.tcp_state {
-            TcpState::Listening { abort, .. } => {
+            TcpState::Listening { abort, listener } => {
+                unsafe { libc::close(listener.as_raw_fd()) };
                 eprintln!("DROP LISTENER");
                 _ = abort.send(());
                 Ok(())

just as a very quick PoC, since I did not really find a nice way to close the listener yet, this seems to have fixed the issue.

Of course, I got

fatal runtime error: IO Safety violation: owned file descriptor already closed

but I guess that's expected :D

I tried also wrapping the listener in an Option<std::sync::Mutex<TcpListener>>, but that got pretty awkward pretty quick although it potentially can work as well

view this post on Zulip Joel Dice (Feb 20 2025 at 16:38):

Yeah, I figured we'd need to use a Mutex somewhere given that the futures need to be Send + Sync

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 16:39):

ah, actually, we could also use tokio::spawn directly and communicate with the BackgroundTask via a channel

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 16:39):

that way the drop can just use tokio task machinery directly

view this post on Zulip Joel Dice (Feb 20 2025 at 16:40):

yeah, I could see that working

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 17:07):

hmm, it mostly works, hitting some non-determinism, want to take a look?

view this post on Zulip Joel Dice (Feb 20 2025 at 17:07):

sure, same google meet link?

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 17:08):

yes, will be there in a sec

view this post on Zulip Ralph (Feb 20 2025 at 17:31):

you people are rocking

view this post on Zulip Roman Volosatovs (Feb 20 2025 at 18:22):

took me 3 different channels of 3 different types to get there, but got tcp_bind test consistently working https://github.com/bytecodealliance/wasip3-prototyping/pull/17 @Joel Dice

move TCP listener into a separate Tokio task and add state synchronisation to ensure it's dropped before TcpSocket::drop returns. We should be able to simplify this once tasks spawned via Acces...

view this post on Zulip Joel Dice (Feb 20 2025 at 18:25):

Yikes, that drop implementation is complicated. This should make it a lot simpler:

type Spawned =
    Arc<Mutex<Option<Pin<Box<dyn Future<Output = Result<()>> + Send + Sync + 'static>>>>>;
/// Handle to a spawned task which may be used to abort it.
pub struct SpawnHandle(Spawned);

impl SpawnHandle {
    /// Abort the task.
    pub fn abort(&self) {
        *self.0.lock().unwrap() = None;
    }

    /// Return an [`AbortOnDropHandle`] which, when dropped, will abort the
    /// task.
    pub fn abort_handle(&self) -> AbortOnDropHandle {
        AbortOnDropHandle(self.0.clone())
    }
}

/// Handle to a spawned task which will abort the task when dropped.
pub struct AbortOnDropHandle(Spawned);

impl Drop for AbortOnDropHandle {
    fn drop(&mut self) {
        *self.0.lock().unwrap() = None;
    }
}

view this post on Zulip Joel Dice (Feb 20 2025 at 18:25):

I should have a PR up by the end of the day.

view this post on Zulip Joel Dice (Feb 20 2025 at 18:42):

Actually, the SpawnHandle/AbortOnDropHandle stuff is a bit trickier than I realized. I need to not just clear the Option but also wake the waker (i.e. the FuturesUnordered waker, in this case) so it knows to poll the wrapper future one last time and remove it from the set. Otherwise the wrapper future will be stuck in the FuturesUnordered forever.

view this post on Zulip Joel Dice (Feb 20 2025 at 18:43):

It's doable, just need to spend some more time on it.

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 12:43):

Got all TCP tests working https://github.com/bytecodealliance/wasip3-prototyping/pull/20

This is a follow-up on #1 and #17 , which ensures the wasi:sockets TCP implementation is complete and fully tested using the adapted wasip2 test suite. There's only one item I left a TODO about...

view this post on Zulip Ralph (Feb 21 2025 at 13:05):

you people POUNDING!

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 15:34):

@Joel Dice there's a merge conflict in https://github.com/bytecodealliance/wasip3-prototyping/pull/18 currently, however https://github.com/bytecodealliance/wasip3-prototyping/pull/20 can be merged cleanly and it increases test coverage.
How about we merge https://github.com/bytecodealliance/wasip3-prototyping/pull/20 now and I rebase https://github.com/bytecodealliance/wasip3-prototyping/pull/18 on the resulting main?

This is yet another major rework of concurrent_imports; this time, the goal is to support add_to_linker_get_host properly such that input and output types of the host_getter param need not be the s...
This is a follow-up on #1 and #17 , which ensures the wasi:sockets TCP implementation is complete and fully tested using the adapted wasip2 test suite. There's only one item I left a TODO about...

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 15:47):

pushed a rebased version to https://github.com/bytecodealliance/wasip3-prototyping/tree/dicej/another-bindgen-refactor-rebase

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - GitHub - bytecodealliance/wasip3-prototyping at dicej/another-bindge...

view this post on Zulip Joel Dice (Feb 21 2025 at 15:54):

Yup, sounds good; I just merged #20

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 15:55):

Awesome, should I push to your branch then?

view this post on Zulip Joel Dice (Feb 21 2025 at 15:55):

Sure, thanks!

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 15:59):

pushed. just a heads-up, I'm noticing some flakiness in tcp_connect test, let's see if switching to the new spawn functionality fixes that. Otherwise, we can ignore it for now

view this post on Zulip Joel Dice (Feb 21 2025 at 16:01):

FYI, in the past when I've seen non-deterministic test behavior, I've been able to make it more consistent by adding/removing/adjusting sleep calls in host functions (e.g. artificially delaying tcp socket operations), so if we still see issues even with the new spawn feature, that might help with debugging.

view this post on Zulip Roman Volosatovs (Feb 21 2025 at 16:10):

I cancelled the CI run, if I'll manage to fix it, I'll push a fix within next 1.5h, otherwise I'll push an ignore for the flaky ones

view this post on Zulip Roman Volosatovs (Feb 24 2025 at 12:01):

@Joel Dice the fix for the race condition we discovered was fairly trivial https://github.com/bytecodealliance/wasip3-prototyping/pull/23
Note, that I cannot actually use the abort handle machinery out-of-the-box just yet due to the need of explicitly closing the stream write handle. Let's chat about it later today at the status update!

On some occasions Notify::notified() might have been called after the Notify::notify_waiters call in the drop. Since Notify does not record the notification, the task was never receiving it. Receiv...

view this post on Zulip Victor Adossi (Feb 24 2025 at 17:19):

Hey @Pat Hickey wanted to get your opinion on https://github.com/WebAssembly/wasi-http/pull/154

After talking with Joel at the P3 sync, we want to have body.finish not async (since it doesn't have to be, it's simply ferrying along the trailers), but right now creating a new future requires access to the store which currently is only doable from async functions.

This somewhat inconvenient, but brought up the idea that the lack of trailers and trailers that are present but empty are different -- which means option<future<trailers>> might be a reasonable thing to put on the table. Right now, to make future<trailers> work, if there are no trailers, we create a new future to essentially and make sure to write nothing.

I think you were against option<future<trailers>>, am I remembering correctly?

This commit changes wasi:http/types#body.finish to forward the optionally present trailers, rather than retrieve them with the possibility of generating an error along the way. With this change, ca...
We read every piece of feedback, and take your input very seriously.

view this post on Zulip Joel Dice (Feb 24 2025 at 17:46):

To elaborate on what Victor said above: there's currently a limitation in wasmtime-wit-bindgen's Component Model Async support such that sync functions can't create streams or futures, but that's a temporary limitation we plan to address soon, so no need to design around it.

view this post on Zulip Pat Hickey (Feb 24 2025 at 18:49):

thanks for the explanation, I'm fine with what you came up with

view this post on Zulip Victor Adossi (Feb 24 2025 at 19:56):

Thanks! Just to make sure I fully understand -- are you going for creating the future here (no option, i.e. returning future<trailers> no matter what) or returning an option<future<trailers>>?

If the former, a review on https://github.com/WebAssembly/wasi-http/pull/154 would be appreciated! If the latter -- I'll get to making that change ASAP

This commit changes wasi:http/types#body.finish to forward the optionally present trailers, rather than retrieve them with the possibility of generating an error along the way. With this change, ca...

view this post on Zulip Roman Volosatovs (Feb 25 2025 at 10:41):

following the discussion from yesterday, I've replaced the Tokio task/channel magic by AbortOnDropHandle machinery in https://github.com/bytecodealliance/wasip3-prototyping/pull/32, which does not rely on multi-threading anymore.
I think we need to talk a bit more about send and connect.
cc @Alex Crichton @Joel Dice

Switch to AbortOnDropHandle introduced in #18 This simplifies the Drop logic and brings back single-threaded program support. I originally planned to introduce similar constructs for send and conne...

view this post on Zulip Roman Volosatovs (Feb 25 2025 at 18:05):

UDP implementation and tests: https://github.com/bytecodealliance/wasip3-prototyping/pull/33 - with this, we have latest wasip3 wasi:sockets draft fully implemented and tested using adapted wasip2 test suite. Will be starting with wasi:filesystem tomorrow.

Fully implement UDP part of wasi:sockets Follow-up on #25

view this post on Zulip Joel Dice (Feb 25 2025 at 18:12):

I got sidetracked yesterday fixing the soundness issue Alex raised in wasmtime-wit-bindgen's concurrent_imports option, as well as restoring support for &mut T forwarding impls so we can generate add_to_linker functions again. The good news is I got it working (should have a PR up today). The bad news is I didn't work on anything else. These are on my TODO list, though:

view this post on Zulip Joel Dice (Feb 25 2025 at 18:18):

@Roman Volosatovs when you switched to AbortOnDropHandle, how did you handle closing the StreamWriter? Or is that still a TODO blocked on the "auto-closing {Stream|Future}{Writer|Reader} on drop" item I mentioned above?

view this post on Zulip Roman Volosatovs (Feb 25 2025 at 18:38):

I actually did not make any changes in that regard - there are two tasks, both spawned via the store. The tasks communicate over an mpsc.

The producer side deals with all the OS-level stuff, I/O etc. , e.g. it owns the file descriptor (e.g. TCP stream) and it does not use the Accessor at all.
The consumer side owns the StreamWriter and is responsible for closing it once mpsc is closed and/or an unrecoverable error is encountered.

The abort handle of the producer task is stored as part of the resource state and so it's dropped once resource is dropped, triggering, e.g. close of a TCP stream FD.
The consumer task will eventually(likely on next poll) find out that the producer is closed and close the StreamWriter

view this post on Zulip Joel Dice (Feb 25 2025 at 18:39):

Ah, that makes sense -- thanks for the explanation.

view this post on Zulip Joel Dice (Feb 25 2025 at 23:15):

@Alex Crichton @Victor Adossi I've been thinking some more about how to support creating futures and streams in sync host functions, and the easiest thing for the time being is to just tell wasmtime-wit-bindgen to generate an async function if it needs to create a future or stream (even if it doesn't need to await) -- which is exactly what Victor's PR already does. The guest can call that synchronously and everything will work as it should.

Alex and I have ideas about making both the async and sync bindings more flexible and ergonomic in the future, but for the time being I think it's fine to tell the binding generator to generate an async function any time the implementation needs to await or create futures or streams.

We read every piece of feedback, and take your input very seriously.

view this post on Zulip Tomasz Andrzejak (Feb 26 2025 at 14:56):

Hello :wave: this is probably a silly question but could someone explain what's the reason for changing the cli/stdio interface from:

view this post on Zulip Joel Dice (Feb 26 2025 at 15:01):

In the component model, the stream type always represents the readable end of a stream; there's no equivalent to output-stream for the writable end; which is to say that the component which creates a stream using stream.new can only give away the readable end and keep the writable end for itself. So the only way to hook a stream up to stdout or stderr is to create that stream using stream.new, hold on to the writable end, and pass the readable end to e.g. setStdout.

view this post on Zulip Joel Dice (Feb 26 2025 at 16:21):

The setStdout/setStderr API does raise an interesting question, though: If I compose two components and they both call setStdout, will one overwrite the other? I.e. is only one of the components going to be able to write to stdout?

view this post on Zulip Joel Dice (Feb 26 2025 at 16:23):

I imagine the host could maintain some kind of magic per-component state so that they don't overwrite each other, but I'm not sure that would be virtualizable by a guest component.

view this post on Zulip Roman Volosatovs (Feb 26 2025 at 16:31):

@Joel Dice @Alex Crichton following our earlier discussion: https://github.com/WebAssembly/wasi-sockets/pull/119

I'll also address the listen/receive stream capturing the lifetime of the socket resource later. (on that note, lazy question: does Rust guest wit-bindgen actually support this correctly, or does a returned stream capture the lifetime of the resource borrow the method was called on, in other words, are returned streams/futures 'static?)

Futures can resolve to "no value" - use that property to simplify the signature and simply do not resolve to a result on success. As a side effect, this allows host implementations to fea...

view this post on Zulip Joel Dice (Feb 26 2025 at 16:31):

I just opened an issue about the set-stdout/set-stderr question I raised above: https://github.com/WebAssembly/wasi-cli/issues/64

In the 0.3.0-draft stdio.wit, the (currently undocumented) set-stdout and set-stderr functions raise the question of what happens when they are called more than once (either by the same component o...

view this post on Zulip Alex Crichton (Feb 26 2025 at 21:46):

Joel there's changes in wasm-tools now to update various intrinsics and line up with the spec, do you want to coordinate about landing this within wasmtime? I ask because jsturtevant is working on a bugfix at wasm-tools#2076 which will unblock wasi-tls landing (this is completely unrelated to async), but I bring this up as that'll require updating wasm-tools.

The literal update is pretty modest but I suspect the actual changes to trampolines/tests to be a bit more invasive. In particular core wasm signatures are changing and things like waitable sets now need to be both created and destroyed around usages too

fixes: #1995 When a new interface is marked as @unstable (feature = somefeaturegate) and it uses a stable type from another package via use package:interface/type.{name} the resulting package shoul...
fixes: #10089 This adds a crate that provides the Wasmtime host implementation for the wasi-tls API. The wasi-tls world allows WebAssembly modules to perform SSL/TLS operations, such as establishin...
Standalone JIT-style runtime for WebAsssembly, using Cranelift - wip · alexcrichton/wasmtime@f472847

view this post on Zulip Joel Dice (Feb 26 2025 at 21:47):

Getting that upstream sounds fine to me and won't disrupt the WASIp3 work until we try to merge it into the wasip3-prototyping repo, but we don't need to do that right away. So no need to delay the former, and I'm happy to help if anything comes up.

view this post on Zulip Alex Crichton (Feb 26 2025 at 21:48):

ok sounds good, I'll forge ahead when the update is necessary

view this post on Zulip Alex Crichton (Feb 26 2025 at 21:48):

although same question, but this time from wit-bindgen -- should I be careful about updating there or "update at will"?

view this post on Zulip Joel Dice (Feb 26 2025 at 21:49):

I'd say update at will; we can delay updating the dep in the wasip3-prototyping repo as well.

view this post on Zulip Roman Volosatovs (Feb 27 2025 at 17:04):

@Joel Dice https://github.com/bytecodealliance/wasip3-prototyping/pull/40

cc @dicej

view this post on Zulip Roman Volosatovs (Feb 27 2025 at 17:10):

test scenario::round_trip::async_round_trip_stackless_sync_import has been running for over 60 seconds

looks like CI caught it as well

view this post on Zulip Roman Volosatovs (Feb 27 2025 at 17:14):

filed an issue https://github.com/bytecodealliance/wasip3-prototyping/issues/41

Currently, calling a host export implemented as async using concurrent_import as a sync import from an async export in the guest causes a deadlock. See #40 for a test case with a repro

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:01):

question on CI: there's a copy of main.yml but trimmed down -- is this because when I originally made the repo I disabled main.yml (named "CI") and it was thought we needed to copy that to get something running?

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:02):

I'm discovering in https://github.com/bytecodealliance/wasip3-prototyping/pull/43 that there's some sort of mixture or something going on where CI isn't actually running right now

This is an attempt at merging the upstream repo back into this repo to bring everything up-to-date.

view this post on Zulip Joel Dice (Feb 27 2025 at 21:02):

Probably. In any case we're using wasip3-prototyping.yml (which we copied and modified) for PRs

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:02):

or rather some jobs aren't running

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:02):

is the goal to basically match the wasmtime repo?

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:03):

if so I can set that up

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:03):

(merge queues and all)

view this post on Zulip Joel Dice (Feb 27 2025 at 21:03):

kind of, except we're skipping cargo vet for now

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:03):

just vet? anything else?

view this post on Zulip Victor Adossi (Feb 27 2025 at 21:03):

That would be awesome -- I set up the copy there to mostly do the same thing as main but hopefully run slightly faster without tests that we wouldn't impact

view this post on Zulip Joel Dice (Feb 27 2025 at 21:03):

and I think we added another test job for async specifically

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:03):

the async tests aren't run otherwise?

view this post on Zulip Joel Dice (Feb 27 2025 at 21:04):

maybe not? I haven't looked closely :shrug:

view this post on Zulip Victor Adossi (Feb 27 2025 at 21:04):

Yep, and another job for async specifically, mostly for visibility, the original goal was to only run those but figured there could be downstream effects

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:05):

ok I'll work to try to figure out what's going on and see if changes are necessary

view this post on Zulip Victor Adossi (Feb 27 2025 at 21:05):

the async tests are under misc I'm not sure if that's covered under test by default but entirely could be!

view this post on Zulip Victor Adossi (Feb 27 2025 at 21:05):

Yup happy with any changes there -- having merge queues and any tests that are necessary re-enabled would be nice

view this post on Zulip Joel Dice (Feb 27 2025 at 21:06):

To be clear, the extra job Victor added runs cargo test -p component-async-tests, but there are other async-related tests elsewhere (e.g. bindgen and WA(S)T tests)

view this post on Zulip Joel Dice (Feb 27 2025 at 21:07):

I would expect cargo test --all to run the component-async-tests, but maybe it wasn't for some reason?

view this post on Zulip Joel Dice (Feb 27 2025 at 21:07):

I don't even know if CI runs cargo test --all

view this post on Zulip Victor Adossi (Feb 27 2025 at 21:11):

Ah it does by default, run-tests.sh uses --workspace, wasn't necessary for me to use -p component-async-tests by default, but did like having it broken out like fiber. Certainly happy with having it all get back to a state more similar to upstream

view this post on Zulip Alex Crichton (Feb 27 2025 at 21:34):

ok in the main merge I'm deleting wasip3-prototyping.yml, I disabled cargo vet for anything outside of bytecodealliance/wasmtime (I'll land that upstream) and I'll work through the remaining failures

I'll have a follow-up which splits out the component-async-tests package to its own CI bucket which should still run on PRs by default.

I'm also enabling the merge queue. For now it's set as "merge & commit" as the strategy, but I'm only going to leave that for this one PR. The merge strategy is defined at the repo level, not the PR level, so my plan is to change that to "squash & merge" like wasmtime has after this merge lands

This is an attempt at merging the upstream repo back into this repo to bring everything up-to-date.

view this post on Zulip Roman Volosatovs (Feb 27 2025 at 22:13):

Squash & merge would complicate the eventual upstream contribution - I've set the strategy to "rebase" to allow for cherry-picking commits later

If others prefer squashes - that's fine, but I'd like to be able to keep merging my WASI PRs with rebase

view this post on Zulip Alex Crichton (Feb 27 2025 at 22:14):

oh sure I can leave that turned on yeah

view this post on Zulip Alex Crichton (Feb 27 2025 at 22:15):

it'll mostly just be annoying that if a merge from upstream back to wasip3 happens we'll have to update merge queue settings around that

view this post on Zulip Roman Volosatovs (Feb 27 2025 at 22:29):

Giving it a bit more thought, I don't think I actually mind squash merges at this point, my upcoming PRs should be rather small/well-scoped, so rebase or squash should not really matter any more, the "incremental" commits I cared about are already in main

view this post on Zulip Alex Crichton (Feb 27 2025 at 22:32):

ok set to squash + merge and the next PR should go through smoothly in theory

view this post on Zulip Roman Volosatovs (Feb 28 2025 at 10:40):

Looks like CI is broken https://github.com/bytecodealliance/wasip3-prototyping/actions/runs/13586320199/job/37982051541

This occurred twice trying to merge https://github.com/bytecodealliance/wasip3-prototyping/pull/46

I'll go ahead and merge manually on CLI

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - CI · bytecodealliance/wasip3-prototyping@a43a8ba
This changes the return types of {Future|Stream}Writer::write to report whether the read end was closed before all values were delivered. In the case of StreamWriter, it also auto-closes the write...

view this post on Zulip Roman Volosatovs (Feb 28 2025 at 12:59):

wasi:filesystem https://github.com/bytecodealliance/wasip3-prototyping/pull/38

going to investigate the flaky UDP test and start wasi:cli implementation

wasi:filesystem implementation. The preview2 filesystem-specific test suite seems to be pretty minimal - it includes only 1 test - it appears that most of FS oppperations are tested as part of cli ...

view this post on Zulip Alex Crichton (Feb 28 2025 at 15:33):

ci should hopefully be fixed here

I always forget this and it always bites us within a few months. Alas.

view this post on Zulip Roman Volosatovs (Feb 28 2025 at 15:34):

awesome, thanks @Alex Crichton !

view this post on Zulip Joel Dice (Feb 28 2025 at 18:25):

Heads up that I had a flash of inspiration last night regarding improving the{Stream|Future}{Writer|Reader} host API ergonomics, and the implementation is looking good so far; aiming to have PR up by EOD. In short, you'll be able to read, write, and close either end of a stream or future without needing a StoreContextMut. Ideally you wouldn't need one for creating streams or futures either, but that's going to be more difficult to achieve, so I'm punting on that for now.

view this post on Zulip Joel Dice (Mar 01 2025 at 00:43):

Here's the PR: https://github.com/bytecodealliance/wasip3-prototyping/pull/50

This adds close-on-drop functionality to {Stream|Future}{Writer|Reader} and support for reading and writing without a StoreContextMut. Both of those features are enabled by spawning background tas...

view this post on Zulip Joel Dice (Mar 01 2025 at 00:44):

@Roman Volosatovs I haven't added a way to get a Future that resolves when the other end of a stream/future is closed yet, but I'm planning to do that Monday.

view this post on Zulip Roman Volosatovs (Mar 03 2025 at 08:35):

I'm traveling today, so won't be able to make it to the status update call. On my way I'll be working on porting the rest of the p2 tests and finishing up the wasi:cli.
@Joel Dice do I understand correctly that you already have wasip3 wasi:http implementation complete or should I work on that as well?

view this post on Zulip Roman Volosatovs (Mar 03 2025 at 11:28):

wasi:cli https://github.com/bytecodealliance/wasip3-prototyping/pull/47
assuming that wasi:http is already complete, all of WASIp3 is implemented in the prototyping repo.
I'll be focusing on testing, refactoring and bug fixes now. hopping on a plane soon

Just the implementation without tests for now, I'll be porting tests in the meantime. Refs #51

view this post on Zulip Joel Dice (Mar 03 2025 at 14:50):

Nice work!

All I've done for wasi:http is sketch an implementation for testing purposes, based on a now-out-of-date draft. @Victor Adossi has done some work to partially sync it with the latest draft, but not entirely.

In any case, that implementation was only ever meant for runtime testing and examples; it has a bunch of TODOs, and I haven't tried to get the existing wasmtime-wasi-http tests ported over. So if you have bandwidth to work on any of that, it would certainly be appreciated!

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Roman Volosatovs (Mar 03 2025 at 14:58):

Ok, I'll work on HTTP then!

view this post on Zulip Alex Crichton (Mar 03 2025 at 15:27):

I'll also have to dip out a bit early from the sync to run an errand too, I've mostly been working on the low-level tooling of wasmparser/etc sync'ing that with the spec and then working my way up to wit-bindgen with the goal of getting a C generator in mind (but also understanding the Rust generator at the same time)

view this post on Zulip Roman Volosatovs (Mar 04 2025 at 15:51):

It appears that wasm32-wasip2 target is not currently supported by Rust wasip3 components, is that right?

I'm getting:

  = note: error: failed to parse core wasm for componentization

          Caused by:
              0: decoding custom section component-type:wit-bindgen:0.39.0:wasi:cli@0.3.0:command:encoded world
              1: invalid leading byte (0x66) for component defined type (at offset 0xda)

when trying to build a component with cargo build --target wasm32-wasip2 --release on:

cargo 1.84.1 (66221abde 2024-11-19)

wit-bindgen e0d2b889411acf60738dcd976ed5373f7a81e651

view this post on Zulip Joel Dice (Mar 04 2025 at 15:53):

Ah, yeah, I guess that makes sense given that wasm-component-ld is using an older version of wit-encoder. We'd need a build with an updated dep.

view this post on Zulip Roman Volosatovs (Mar 04 2025 at 15:54):

so for now we should build for wasm32-unknown-unknown and componentize manually then?

view this post on Zulip Joel Dice (Mar 04 2025 at 15:54):

or wasm32-wasip1

view this post on Zulip Victor Adossi (Mar 04 2025 at 15:54):

we're building with wasm32-wasip1 and adapting right now in the build scripts

view this post on Zulip Victor Adossi (Mar 04 2025 at 15:54):

https://github.com/bytecodealliance/wasip3-prototyping/blob/main/crates/test-programs/artifacts/build.rs

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Roman Volosatovs (Mar 04 2025 at 16:19):

wasmtime run runs wasip3 components now https://github.com/bytecodealliance/wasip3-prototyping/pull/60 :)

With this I was able to run: mod bindings { wit_bindgen::generate!({ world: "wasi:cli/command", async: { exports: [ "wasi:cli/run@0.3....

view this post on Zulip Alex Crichton (Mar 05 2025 at 15:32):

as a heads up I'm going to start the process today of updating wasm-tools everywhere. Stuff's probably gonna be broken for awhile.

view this post on Zulip Joel Dice (Mar 05 2025 at 15:33):

:thumbs_up: BTW, I'm finishing up addressing your feedback on https://github.com/bytecodealliance/wasmtime/pull/10106 and plan to merge it when I'm done, in case you want to wait for that.

This is another piece of #9582 which I'm splitting out to make review easier. The fused.wast test exercises fused adapter generation for various flavors of intercomponent async->async, async...

view this post on Zulip Alex Crichton (Mar 05 2025 at 15:33):

will do

view this post on Zulip Alex Crichton (Mar 05 2025 at 15:33):

tune in at 7 for today's episode of "race to rebase"

view this post on Zulip Joel Dice (Mar 05 2025 at 17:23):

@Alex Crichton #10106 is merged

view this post on Zulip Joel Dice (Mar 06 2025 at 14:35):

@Alex Crichton I'll merge upstream Wasmtime into wasip3-prototyping unless you've already started that.

view this post on Zulip Joel Dice (Mar 06 2025 at 14:38):

After that, I'm planning to work on https://github.com/bytecodealliance/wasmtime/issues/10338 and then host support for waitable sets. @Alex Crichton are you planning to work on guest (i.e. wit-bindgen) support for waitable sets?

I'm about to commit code in #10314 where the new canonical options specified on task.return, now present after a wasmparser update, are going to be ignored during compilation of the trampoline. Thi...

view this post on Zulip Alex Crichton (Mar 06 2025 at 14:40):

I haven't started the merge feel free

view this post on Zulip Alex Crichton (Mar 06 2025 at 14:40):

You might have to temporarily disable tests I don't think my wit bindgen tests are sufficient just yet

view this post on Zulip Roman Volosatovs (Mar 06 2025 at 19:15):

@Joel Dice https://github.com/bytecodealliance/wit-bindgen/pull/1197

the fix was pretty simple, as discussed.

btw, I noticed that wit-bindgen in main appears to be broken, and I had to roll back to the last-known-good commit for testing this in my wasi fork. I'll file an issue later upstream, but for now it can be reproduced with https://github.com/rvolosatovs/wasi/tree/feat/p3 and using latest main of wit-bindgen. Just thought it's important to call it out

cc @dicej This fixes bytecodealliance/wasip3-prototyping#66 Note, that eventually we might want go get smarter about this (or not) e.g. see https://docs.rs/tokio/latest/tokio/task/index.html#cooper...
Experimental WASI API bindings for Rust. Contribute to rvolosatovs/wasi development by creating an account on GitHub.

view this post on Zulip Joel Dice (Mar 06 2025 at 19:16):

Yeah, I hit that too. Fixing it now

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:17):

oh is it the double fn new problem?

view this post on Zulip Joel Dice (Mar 06 2025 at 19:17):

yup

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:17):

I ran into that on https://github.com/bytecodealliance/wit-bindgen/pull/1192 as well, I can also split out the fix

As I've read more and more of the Rust async runtime support and other various bits and pieces I've wanted more and more the ability to easily write tests for guest interactions with the ho...

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:17):

it wasn't caught on CI because it's only a problem when things are compiled to wasm which the codegen tests aren't

view this post on Zulip Joel Dice (Mar 06 2025 at 19:19):

I think for the time being we need to test async-related wit-bindgen changes manually against wasip3-prototyping to catch stuff like that. Not ideal (and maybe not practical when stuff is out of sync), but something to aim for, at least.

view this post on Zulip Joel Dice (Mar 06 2025 at 19:19):

wasip3-prototyping is the only place we have runtime tests involving guest bindings for now

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:19):

yeah I forgot to do it on that change :(

view this post on Zulip Joel Dice (Mar 06 2025 at 19:23):

No worries; looking forward to having runtime tests in the wit-bindgen repo so we don't have to remember anymore.

view this post on Zulip Joel Dice (Mar 06 2025 at 19:27):

Making progress on the merge, but now hitting this:

  thread 'main' panicked at crates/test-programs/artifacts/build.rs:184:10:
  module can be translated to a component: failed to decode world from module

  Caused by:
      0: module was not valid
      1: failed to resolve import `$root::[task-backpressure]`
      2: no top-level imported function `[task-backpressure]` specified

No surprise; wit-bindgen hasn't been updated to match the latest wit-encoder. @Alex Crichton if you haven't already started that, I can dive in.

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:28):

no please do

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:28):

but I also don't mind taking this

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:28):

I'm studying async tests right now

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:28):

this is also making me rethinking if we should organize things a bit different w.r.t wit-bindgen and wasip3-prototyping,b ut that's for the side

view this post on Zulip Joel Dice (Mar 06 2025 at 19:29):

Well you are faster than me at pretty much everything, so feel free to take it; I could work on the task.return options stuff while you do that.

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:29):

wanna share your p3 branch-in-progress?

view this post on Zulip Joel Dice (Mar 06 2025 at 19:30):

yup, just a sec

view this post on Zulip Joel Dice (Mar 06 2025 at 19:32):

https://github.com/bytecodealliance/wasip3-prototyping/pull/68

We read every piece of feedback, and take your input very seriously.

view this post on Zulip Joel Dice (Mar 06 2025 at 19:33):

oops, just realized I left a [patch] in the Cargo.toml to point to a local wit-bindgen; I'll revert that part

view this post on Zulip Joel Dice (Mar 06 2025 at 19:33):

(although it might be useful for what you're doing :)

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:33):

heh that was step 1 for me lol

view this post on Zulip Alex Crichton (Mar 06 2025 at 19:56):

I've hit a wit-component bug, will take a moment to fix

view this post on Zulip Joel Dice (Mar 06 2025 at 20:54):

@Alex Crichton can you confirm that I'm remembering this correctly: In order to make the runtime task.return validation a single comparison, we're going to intern the dfg::CanonicalOptions in ComponentTypesBuilder (call it e.g. CanonicalOptionsIndex), then pair that with the TypeTupleIndex we're already using to intern the component return type, producing a third interned thing (call it e.g. TaskReturnIndex) that represents the pair. Then at runtime, we compare the two TaskReturnIndexes and trap if they don't match. Does that sound right?

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:12):

Eventually yeah, but for now it's probably easier to just shepherd along options individually and check then all

view this post on Zulip Joel Dice (Mar 06 2025 at 21:13):

Already started down the intern path :). Shouldn't be a lot of work; just wanted to make sure it wasn't the wrong approach.

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:13):

Be careful to only intern a few things though

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:13):

Since the spec says we only check a few minor options

view this post on Zulip Joel Dice (Mar 06 2025 at 21:14):

ok, so create a new struct with only the relevant options, then

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:14):

I also realize we need to confirm what function equality means in the spec because interning misses runtime reexpots

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:14):

But yeah new steuct

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:15):

Er memory equality I mean, but functions too with realloc

view this post on Zulip Joel Dice (Mar 06 2025 at 21:17):

ok, so "unusual" components might fail the the runtime test even though they're actually following the rules?

view this post on Zulip Joel Dice (Mar 06 2025 at 21:17):

but we'll still definitely trap any components that aren't following the rules?

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:17):

Right

view this post on Zulip Joel Dice (Mar 06 2025 at 21:20):

Would RuntimeMemoryIndex, RuntimeReallocIndex, etc. help at all with the false traps?

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:21):

No, that's what you're interning over basically

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:22):

We basically treat core modules as black boxes right now and don't detect reexports

view this post on Zulip Joel Dice (Mar 06 2025 at 21:30):

Should I be doing the interning in ComponentTypesBuilder? It currently doesn't know anything about memories or reallocs; those appear to be interned in LinearizeDfg instead. Is it okay to intern a struct that has e.g. a RuntimeMemoryIndex field in a ComponentTypes{Builder}?

view this post on Zulip Alex Crichton (Mar 06 2025 at 21:30):

Probably in dfg

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:48):

Alex Crichton said:

I've hit a wit-component bug, will take a moment to fix

the rabbit hole is going deeper...

view this post on Zulip Joel Dice (Mar 06 2025 at 22:49):

Let me know if I can help with anything.

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:50):

nah it's all preexisting issues in wit-component

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:50):

tl;dr; the --dummy support didn't emit intrinsics for things like futures/streams/task.return/etc, meaning that was never exercised in fuzzing, and the buggy module originally in wasip3-prototyping was exercising this

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:50):

so I first updated --dummy to import all async intrinsics, and now that's turning up at least one other independent bug in wit-component

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:51):

so need to sort through these all basically

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:52):

this all has to do with type encoding and making sure things are encoded in the right spot, and that's all super subtle and I always forget about it and just hope the fuzzer finds things (which it is now)

view this post on Zulip Joel Dice (Mar 06 2025 at 22:54):

Yeah, I've been eager to start (and also dreading) fuzzing all the things; glad we're finally starting to do that.

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:54):

oh this is the fuzzer already going in roundtrip_wit in wasm-tools, and it's been doing async things for awhile

view this post on Zulip Alex Crichton (Mar 06 2025 at 22:54):

this is just expanding the set of things it does

view this post on Zulip Alex Crichton (Mar 06 2025 at 23:25):

ok 4 other bugs fixed and the fuzzer now reached the original one I started with, yay!

view this post on Zulip Joel Dice (Mar 06 2025 at 23:44):

I've done the task.return type/options interning we discussed. It compiles, at least. Will test once the merge is complete.

view this post on Zulip Alex Crichton (Mar 06 2025 at 23:48):

this is going to take me a second, I pushed up my work-in-progress to your PR

view this post on Zulip Alex Crichton (Mar 06 2025 at 23:49):

the next step is adding struct WaitableSet to async_support.rs. Not hard but the fuzzer is finding more bugs in the background, you want to take over updating wit-bindgen from here?

view this post on Zulip Joel Dice (Mar 06 2025 at 23:51):

Yup; I'll start on that tomorrow morning. Thanks for getting it this far!

view this post on Zulip Joel Dice (Mar 07 2025 at 00:32):

Nevermind, I started it this evening. I've got wit-bindgen generating code to use the waitable-set intrinsics, and wit-component is happy with that, but wit-component is now choking on https://github.com/bytecodealliance/wasip3-prototyping/blob/main/crates/test-programs/src/bin/async_transmit_callee.rs:

  thread 'main' panicked at /home/dicej/.cargo/git/checkouts/wasm-tools-3a47d954f2d24d2f/311b6fa/crates/wit-component/src/encoding.rs:557:47:
  IndexMap: key not found

I'll try debugging it; might be related to one of the issues the fuzzer found?

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:33):

yeah I found another issue or two

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:34):

update the wit-component dep

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:34):

via cargo update -p wit-component and I think it should pick up a fix I just pushed

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:34):

and if it still panics I'll dig in more

view this post on Zulip Joel Dice (Mar 07 2025 at 00:35):

same panic

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:35):

guh ok if you can push your work I'll dig in

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:36):

oh wait

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:36):

fuzzer just hit it

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:36):

time to spelunk

view this post on Zulip Joel Dice (Mar 07 2025 at 00:37):

I'll push what I have, anyway. It's just a stub so far; not merge-able.

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:39):

oh wait maybe I have a bad rebase

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:39):

I broke a preexisting test

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:39):

ok try pulling again

view this post on Zulip Joel Dice (Mar 07 2025 at 00:41):

looks good; hitting another issue now, but an expected one

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:41):

nice

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:41):

gogo fuzzers

view this post on Zulip Joel Dice (Mar 07 2025 at 00:45):

nice, got cargo clippy --workspace --all-targets green now

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:45):

the next gauntlet: acutally running the test heh

view this post on Zulip Joel Dice (Mar 07 2025 at 00:46):

I know; I kind of want to make that a problem for Tomorrow Joel

view this post on Zulip Alex Crichton (Mar 07 2025 at 00:46):

Today Joel thanks you for your service

view this post on Zulip Joel Dice (Mar 07 2025 at 00:50):

about half of the integration tests are passing; not bad. The rest are dying with cranelift signature mismatch errors; presumably something wrong with in compiler/component.rs

view this post on Zulip Joel Dice (Mar 07 2025 at 00:51):

or fact/trampoline.rs maybe

view this post on Zulip Joel Dice (Mar 07 2025 at 00:51):

either way, it's Tomorrow Joel's problem

view this post on Zulip Joel Dice (Mar 07 2025 at 16:23):

All the integration tests are now passing. Just some WAT tests failing now; should be easy to fix.

view this post on Zulip Joel Dice (Mar 07 2025 at 16:27):

@Alex Crichton How would you feel about merging https://github.com/dicej/wit-bindgen/commit/b518c80c3707e5df8e890acb0444cf9f2588a8fc (which hard-codes the waitable-set handle to zero, since Wasmtime is currently ignoring it) as a temporary measure just to get things working again? I'll follow that up with proper waitable-set PRs for both wit-bindgen and wasip3-prototyping, but I don't want to block getting the merge into main while I'm doing that.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

view this post on Zulip Roman Volosatovs (Mar 07 2025 at 16:38):

I'm hitting the unreachable! in https://github.com/bytecodealliance/wit-bindgen/blob/b4d62a45c2c0d697a0ce88f0686fe05a7cba4805/crates/guest-rust/rt/src/async_support/stream_support.rs#L342-L349

thread '<unnamed>' panicked at /Users/rvolosatovs/.cargo/git/checkouts/wit-bindgen-b65103eb40fd7b8c/554b482/crates/guest-rust/rt/src/async_support/stream_support.rs:347:48:
internal error: entered unreachable code

has anyone seen it before? Any ideas what might be going wrong?
@Joel Dice happy to jump on a call to look at it together if you're available

A language binding generator for WebAssembly interface types - bytecodealliance/wit-bindgen

view this post on Zulip Joel Dice (Mar 07 2025 at 16:42):

That means the guest has received a stream handle it thinks it already owns. Yeah, a call would be good.

view this post on Zulip Joel Dice (Mar 07 2025 at 16:43):

As usual, if you can provide a (somewhat) minimized test case that would be ideal.

view this post on Zulip Roman Volosatovs (Mar 07 2025 at 16:45):

are you free now?

view this post on Zulip Joel Dice (Mar 07 2025 at 16:45):

yup

view this post on Zulip Roman Volosatovs (Mar 07 2025 at 16:45):

I'll send you a link in a few minutes

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:05):

How would you feel about merging https://github.com/dicej/wit-bindgen/commit/b518c80c3707e5df8e890acb0444cf9f2588a8fc

sounds reasonable to me yeah

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:06):

my hope is to soon start digging more into refactorings for the rust guest bindings with more test cases using wit-bindgen test

view this post on Zulip Joel Dice (Mar 07 2025 at 17:11):

BTW, I just chatted with Luke, pointing out that a realloc option for task.return doesn't make sense because it only needs to lift values. He's going to remove that from the spec, and we may need to tweak the validation rules in wasmparser to match.

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:11):

right!

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:12):

that reminds me to open an issue about memory equality

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:25):

I posted https://github.com/bytecodealliance/wasm-tools/pull/2086 for removing the realloc option (shouldn't affect much) and https://github.com/WebAssembly/component-model/issues/464 for clarifying memory equality (which affects what sort of interning we can do)

This'll soon be updated in the spec as well, but task.return is only lifting values so there's no need for realloc, so go ahead and forbid it from being present on the task.return intrinsic.
The runtime validation of task.return checks that the canonical options are the same as the options used during the original lift (or at least the relevant subset). This includes the memory option ...

view this post on Zulip Joel Dice (Mar 07 2025 at 17:35):

@Alex Crichton Roman can provide more detail, but the issue he ran into above is the one you pointed out last week: writing to a "local" stream, then giving the read end away before that write completes. He's going to work around it, but now we have a real-world example.

view this post on Zulip Joel Dice (Mar 07 2025 at 17:36):

I guess that should be easier to fix than the opposite case (e.g. writing to a "remote" stream and then receiving the read end before the write completes).

view this post on Zulip Alex Crichton (Mar 07 2025 at 17:38):

makes sense yeah, and once we have things lined up again I'll start working on tests and fixes for these issues

view this post on Zulip Joel Dice (Mar 07 2025 at 17:40):

I'm almost done fixing the remaining tests, then will push what I have.

view this post on Zulip Joel Dice (Mar 07 2025 at 18:00):

All tests are green; I've pushed what I have to your draft wit-bindgen PR and my draft wasip3-prototyping PR. Now reviewing https://github.com/bytecodealliance/wasm-tools/pull/2084

This commit enhances the --async-callback and --async-stackful arguments to the wasm-tools component embed subcommand when paired with --dummy-names legacy. Specifically the dummy module generated ...

view this post on Zulip Joel Dice (Mar 07 2025 at 19:57):

Coming back to the task-return interning and runtime validation thing: I have all but two tests passing. The two failures appear to be invalid components generated by wit-encoder such that the async-lifted export has a memory option (and indeed should have one), but the corresponding task.return does not. My guess it's due to the return type not needing a memory but the parameter types needing one. Will debug.

view this post on Zulip Alex Crichton (Mar 07 2025 at 19:58):

ok that's a good point, and probably is more spec updates to have

view this post on Zulip Alex Crichton (Mar 07 2025 at 19:58):

basically a "match" saying that a non-present memory is ok to have when the original intrinsic had a memory

view this post on Zulip Alex Crichton (Mar 07 2025 at 19:59):

b/c task.return validation will already require memory if it's needed and otherwise let it lie if it's specified and not needed

view this post on Zulip Alex Crichton (Mar 07 2025 at 19:59):

(which I think this may be the nail-in-the-coffin for the interning strategy)

view this post on Zulip Alex Crichton (Mar 07 2025 at 19:59):

Also, given Luke's response on the upstream issue, interning definitely won't work here

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:00):

spec-wise it's the wrong behavior

view this post on Zulip Joel Dice (Mar 07 2025 at 20:00):

so I need to do three comparisons, then? type, memory, and string-encoding?

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:00):

we could technically intern type+string-encoding, but I don't think that's worth it, so yeah 3 compares

view this post on Zulip Joel Dice (Mar 07 2025 at 20:16):

just to clarify: if either or both the task.return or the lift specify a memory that's not needed, that's ok? I.e. Wasmtime will need to do its own check to see if the memory is really needed based on the return type and set them both to null e.g. during instantiation so that we don't get spurious comparison failures?

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:17):

I think no, what I'd expect is that if they're specified they're asserted to be equal

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:17):

if they happen to not get used, then they just happen to not get used

view this post on Zulip Joel Dice (Mar 07 2025 at 20:18):

ok, so wit-encoder does need to be fixed given that it's generating a lift where it's specified and a corresponding task.return where it's not

view this post on Zulip Joel Dice (Mar 07 2025 at 20:19):

and it's not wasmparser's responsibility to check that, because it can't in general (hence the runtime check)

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:20):

right on wasmparser can't check this, but why would wit-component change?

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:21):

b/c the lift may need it for arguments but not for the results, so it's valid that lift has it but task.return doesn't

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:21):

(and this is where we should update the spec where if task.return is missing it and lift has it then that's ok)

view this post on Zulip Joel Dice (Mar 07 2025 at 20:22):

ok, so then it's not just a simple comparison at runtime is it? One will be null and the other will be non-null, and yet it shouldn't trap because we're saying that's okay.

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:22):

yeah

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:23):

personally I wouldn't worry too much about the cost of these checks, a few conditionals compared to the boxing/copying at the moment is where we're at

view this post on Zulip Joel Dice (Mar 07 2025 at 20:23):

Yeah, not worried about the cost, just want to make sure I've got it correct.

view this post on Zulip Joel Dice (Mar 07 2025 at 20:24):

so if the task.return memory is null and the lift memory is non-null, then we say that's okay because wasmparser would have rejected a task.return that was missing a memory but needed it, correct?

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:25):

correct

view this post on Zulip Alex Crichton (Mar 07 2025 at 20:25):

(or at least that's what I'm envisioning)

view this post on Zulip Joel Dice (Mar 07 2025 at 21:29):

@Alex Crichton is there a way I can pass a reference to a memory to a intrinsic from a fused adapter module such that the host receives a *mut VMMemoryDefinition?

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:30):

no the host will receive Runtime...Index and translate that using *mut ComponentInstance to the definition

view this post on Zulip Joel Dice (Mar 07 2025 at 21:38):

Follow up question: If I have a Option<MemoryIndex> can I turn that into a Option<RuntimeMemoryIndex> somehow? Or is MemoryIndex what I actually want anyway?

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:38):

no you want RuntimeMemoryIndex, and if you plumb everything through dfg/etc I'd expect that to pop out

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:39):

so maybe some layer forgot to do a translation?

view this post on Zulip Joel Dice (Mar 07 2025 at 21:39):

AdapterOptions in fact.rs has a Option<MemoryIndex>

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:39):

or well, at some layer you'll have like a CoreExport, and somewhere during linearization that ...

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:39):

hm adapters

view this post on Zulip Alex Crichton (Mar 07 2025 at 21:40):

gimme 5 then wanna pair on this?

view this post on Zulip Roman Volosatovs (Mar 12 2025 at 16:39):

the EOF parsing the component issue I've mentioned in the call turned out to be wasm-tools version mismatch after all.

view this post on Zulip Victor Adossi (Mar 12 2025 at 16:43):

One thing I also ran into was multi memory being required now where it wasn't before. Not sure how new that is, but moving from one commit of wasip3-prototyping to another it changed

(i.e. Before, my jco branch was using WASM2 | COMPONENT_MODEL | COMPONENT_MODEL_ASYNC and I needed to add MULTI_MEMORY)

view this post on Zulip Alex Crichton (Mar 12 2025 at 17:01):

hm that I'm not entirely sure where that would be coming from...

view this post on Zulip Victor Adossi (Mar 12 2025 at 17:03):

As far as the multi-memory thing goes that MIGHT be unrelated, so I wouldn't pay too much attention to it for now, still going through things on the jco side, there are still a few tests failing there.

But if you want to :rabbit: :hole: :

Update commit
Adding multi memory just a little bit later

This PR is almost certain to be long lived, and contains the ongoing p3 async support for To understand this PR, see the following other resources: https://github.com/WebAssembly/component-model/b...
This PR is almost certain to be long lived, and contains the ongoing p3 async support for To understand this PR, see the following other resources: https://github.com/WebAssembly/component-model/b...

view this post on Zulip Victor Adossi (Mar 12 2025 at 17:05):

unfortunately there's no green test run before the 227.1 update but maybe once the dust settles I'll go back and bisect to get at it properly -- will avoid squashing until then

view this post on Zulip Roman Volosatovs (Mar 12 2025 at 17:05):

I've briefly mentioned it during the call earlier today, but I'll update in the thread as well.
I've managed to make Rust https://github.com/launchbadge/sqlx crate run using wasi:sockets@0.3.0-draft, in particular I was able to make the Postgres todos example in the sqlx repo work with real Postgres instance running in a container.

The code is available here: https://github.com/rvolosatovs/sqlx/tree/feat/wasip3

The component can be run using the Wasmtime CLI from this PR: https://github.com/bytecodealliance/wasip3-prototyping/pull/60

This, of course, was not meant to be a production-ready implementation, but really just a validation, and it looks like we're in a pretty good state.

I've recorded a video, but I'll be happy to write down the step-by-step instructions for running this if anyone is interested (please ask if you'd like that!)
Screen Recording 2025-03-07 at 17.01.24.mov

🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite. - launchbadge/sqlx
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite. - GitHub - rvolosatovs/sqlx at feat/wasip3
With this I was able to run: mod bindings { wit_bindgen::generate!({ world: "wasi:cli/command", async: { exports: [ "wasi:cli/run@0.3....

view this post on Zulip Joel Dice (Mar 13 2025 at 20:21):

@Alex Crichton It turns out we can't postpone supporting context.{get|set} in wasm-tools, wit-bindgen, and wasmtime after all. That's now the only way to save the guest-side task state (i.e. wit-bindgen-rt's FutureState) when returning from an async-with-callback-lifted export. We used to return a pointer to that state so the host could pass it back to us when calling the callback, but now we have to return a CallbackCode ORed with a waitable-set, and since we're avoiding using multivalue, the only way to stash and retrieve our task-local state is with context.{get|set}.

Anyway, assuming you haven't started adding support for those intrinsics anywhere, I'm going to start adding them, since I'll be blocked otherwise.

view this post on Zulip Alex Crichton (Mar 13 2025 at 20:23):

I haven't started yet no

view this post on Zulip Alex Crichton (Mar 13 2025 at 20:23):

feel free

view this post on Zulip Alex Crichton (Mar 13 2025 at 20:23):

makes sense though I see

view this post on Zulip Alex Crichton (Mar 17 2025 at 19:37):

Continuing our discussion today of close-with-error -- I opened https://github.com/WebAssembly/component-model/issues/472 on this topic since I think the current behavior (assuming I'm understanding everything right) is hazardous as trapping conditions depend on what other components are doing, when I'd prefer to have a trapping condition be a purely local decision within a component

Currently as-specified it's required that for an open stream/future that an error is provided when dropping it, I believe for both the reader and the writer end. (please correct me if I'm wrong abo...

view this post on Zulip Alex Crichton (Mar 17 2025 at 19:42):

along the lines of "maybe can change things?" I'm also curious in that issue if it's possible to in theory remove error-context altogether (or basically consider it a WIT extension)

view this post on Zulip Alex Crichton (Mar 17 2025 at 19:42):

but I know I'm missing context, so I'd appreciate it if folks could help fill in the gaps

view this post on Zulip Alex Crichton (Mar 18 2025 at 20:19):

Ok another follow-up here on error-context: https://github.com/WebAssembly/component-model/issues/474 -- basically I'm curious if anyone has thoughts/objections on delaying the error-context type to after 0.3.0 entirely.

I talked today with a few folks and I wanted to write up our thoughts/conclusions into an issue to get some wider feedback before sending a PR to commit to anything. The basic premise is: Emoji-gat...

view this post on Zulip Alex Crichton (Mar 18 2025 at 20:37):

another issue -- https://github.com/WebAssembly/component-model/issues/475 -- with a change to futures/streams where they're likely to be represented in the future with two handles, not just one, and how we're still not 100% certain how this would all work

I talked about this with some folks today but wanted to file an issue with our discussion and follow-ups. Today we realized that there is a previously-unknown issue with the semantics of "just a si...

view this post on Zulip Roman Volosatovs (Mar 19 2025 at 15:32):

In case anyone is interested in discussing wasi:http error handling, we have a call scheduled with @Joel Dice and @Luke Wagner in 30 minutes to discuss https://github.com/WebAssembly/wasi-http/issues/164 and https://github.com/WebAssembly/wasi-http/issues/163

meeting link: meet.google.com/jdu-rpka-gfk

Feel free to join, especially, if you're well familiar with HTTP libraries in various guest languages

Assume the following pseudo-Rust pseudocode implementation of handle, which streams contents of a file represented by some descriptor fd using read-via-stream in response to an incoming request asy...
Components exporting wasi:http@0.3.0-draft/handle.handle cannot correctly forward incoming requests while tracking the body transmit error. Assume an application, which forwards the incoming reques...

view this post on Zulip Roman Volosatovs (Mar 19 2025 at 15:34):

apologies for the short notice, I've been hoping to sum this up and open for discussion earlier this week, but I've been out sick for last 2 days

view this post on Zulip Roman Volosatovs (Mar 19 2025 at 17:45):

@Till Schneidereit @Luke Wagner I've moved away from the auto-close semantics in wasi:http, proposed in https://github.com/WebAssembly/wasi-http/pull/162, instead throwing an error explicitly if live handles exist. Please take a look!

Following our discussion with @lukewagner earlier today: Auto-close any existing, active body resources on repeated calls to request.body or response.body Auto-close any existing, active body stre...

view this post on Zulip Roman Volosatovs (Mar 21 2025 at 15:26):

@Luke Wagner @Till Schneidereit I've updated https://github.com/WebAssembly/wasi-http/pull/162 yet again, would appreciate a review! I'll proceed with the implementation

Make bodies non-optional for request and response constructors Take a future<result<option<trailers>, error-code>> parameter in request/response constructors (refs Defer error-con...

view this post on Zulip Luke Wagner (Mar 21 2025 at 16:21):

Great work on this!

view this post on Zulip Joel Dice (Mar 21 2025 at 18:57):

FYI, I'm doing a pretty deep refactor of concurrent.rs and futures_and_streams.rs in wasip3-prototyping, having realized yesterday that most of the state I had put in Store actually belonged in ComponentInstance. I don't anticipate any major public API changes, so it shouldn't affect the wasmtime-wasi(-http) work, but please avoid making changes to the aforementioned files until my PR is merged (or at least chat with me first).

view this post on Zulip Roman Volosatovs (Mar 31 2025 at 15:29):

I'm running late to the status meeting, feel free to start without me

view this post on Zulip Victor Adossi (Mar 31 2025 at 16:28):

Hey all, rough notes from the status meeting are below (Hey @Joel Dice unfortunately I missed your update so please feel free to fill it in :bow:):

2025/03/31 P3 Sync Meeting Notes

view this post on Zulip Alex Crichton (Mar 31 2025 at 16:34):

thanks for taking notes!

view this post on Zulip Joel Dice (Mar 31 2025 at 16:35):

Thanks for taking notes! My update:

view this post on Zulip Roman Volosatovs (Apr 01 2025 at 16:34):

Looks like I've run into another guest trap while working on wasi:http https://github.com/bytecodealliance/wasip3-prototyping/issues/95

cc @Joel Dice

On dabcd77: cargo test -p wasmtime-wasi-http 'p3::wasi_http_proxy_tests' traps in the guest with: test p3::wasi_http_proxy_tests ... FAILED failures: ---- p3::wasi_http_proxy_tests stdout ---- Erro...

view this post on Zulip Joel Dice (Apr 01 2025 at 16:35):

Thanks for opening the issue; I'll take a look when I get a chance.

view this post on Zulip Alex Crichton (Apr 01 2025 at 16:36):

that one might "just go away" once the wit-bindgen update is merged

view this post on Zulip Roman Volosatovs (Apr 01 2025 at 16:36):

Should I try pulling in some of the changes that you all were working on? Any chance https://github.com/bytecodealliance/wasip3-prototyping/pull/94 could help here?

There's a lot of things in flight and I'm rapidly losing steam today. I wanted to open this up to make other folks aware this is coming though. Sorry I don't have the time/energy right ...

view this post on Zulip Roman Volosatovs (Apr 01 2025 at 16:36):

I'll try rebasing and report

view this post on Zulip Alex Crichton (Apr 01 2025 at 16:36):

that's under the assumption the bug lies in the previous wit-bindgen code, which could also be wrong

view this post on Zulip Joel Dice (Apr 01 2025 at 16:37):

Alex Crichton said:

that one might "just go away" once the wit-bindgen update is merged

I think there are still places in the host code that are too restrictive; we'll see.

view this post on Zulip Joel Dice (Apr 01 2025 at 16:37):

I don't think #94 will make a difference (regarding the trap), but I could wrong.

view this post on Zulip Alex Crichton (Apr 01 2025 at 18:48):

ok @Roman Volosatovs I've merged main with your branch

view this post on Zulip Alex Crichton (Apr 01 2025 at 18:51):

looks like http_0_3_outbound_request_content_length.rs is failing because trailers fail to get sent (I guess something hung up unexpectedly?) and p3::wasi_http_proxy_tests is not finishing so seems like a deadlock of some kind

view this post on Zulip Roman Volosatovs (Apr 01 2025 at 19:18):

Thanks Alex! Both are actually expected for now. For content length one we can't directly translate that from wasip3 - we'll have to call handle to actually try and send a request/response, was just chatting about it with @Pat Hickey
For the incoming HTTP I'll still have to wire up the set of promises to drive guest tasks after return

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 13:48):

@Joel Dice what's the status on https://github.com/bytecodealliance/wasip3-prototyping/pull/97 (I just approved it)? Is it ready for me to build upon in wasi:http work?

This changes a few things about the {Stream|Future}{Writer|Reader} APIs: Both StreamWriter::write and StreamReader::read support buffer reuse by always returning the buffer to the caller (or more...

view this post on Zulip Joel Dice (Apr 03 2025 at 13:50):

I was planning to add some unit tests this morning, but I can go ahead and merge it and add the tests in a separate PR.

view this post on Zulip Joel Dice (Apr 03 2025 at 13:52):

Also, I should probably add BytesBuffer::into_inner and VecBuffer::into_inner methods for retrieving the unwritten items if desired. Let me know if you need either of those; they're trivial to add.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 13:57):

I think incremental changes are good and since the WASI tests pass, that's good enough for me, so I'd say go ahead and merge

view this post on Zulip Joel Dice (Apr 03 2025 at 13:57):

Done!

view this post on Zulip Joel Dice (Apr 03 2025 at 13:57):

(well, queued anyway)

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 14:52):

I definitely will need some way to go from BytesBuffer to Bytes, I'd prefer that to be a From<BytesBuffer> for Bytes
I'm a bit confused though as to why this conversion for BytesMut would not care about offset https://github.com/bytecodealliance/wasip3-prototyping/blob/245d7e1c5a81d3db8c6d88e4f42a1634ba598f8d/crates/wasmtime/src/runtime/component/concurrent/futures_and_streams/buffers.rs#L284 while Deref does https://github.com/bytecodealliance/wasip3-prototyping/blob/245d7e1c5a81d3db8c6d88e4f42a1634ba598f8d/crates/wasmtime/src/runtime/component/concurrent/futures_and_streams/buffers.rs#L298 :thinking:

Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping
Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 14:53):

To be more specific, I'd want to get the Bytes from BytesBuffer, but I'd expect to only get the filled part of it, not the whole underlying buffer

view this post on Zulip Joel Dice (Apr 03 2025 at 14:55):

The idea with BytesMutBuffer::into_inner is that you'd call it when you just want to reuse the BytesMut without caring which parts were written and which weren't. Whereas the Deref impl gives you just the parts which haven't been written yet.

view this post on Zulip Joel Dice (Apr 03 2025 at 14:55):

I could alternatively change BytesMutBuffer::into_inner into fn into_parts(self) -> (BytesMut, usize) if that would be useful.

view this post on Zulip Joel Dice (Apr 03 2025 at 14:56):

(where the usize is the offset to the start of the unwritten bytes)

view this post on Zulip Joel Dice (Apr 03 2025 at 14:58):

With VecBuffer<T>, it will be a bit different since we need to account for non-Copy T, so VecBuffer::into_inner will actually need to do a memmove to shift the unwritten items to the start of the Vec before returning it.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 14:59):

I guess what I'm looking for is roughly https://docs.rs/tokio/latest/tokio/io/struct.ReadBuf.html#method.filled
Maybe there could be a way to just query the offset for BytesBuffer? I'd then be able to call into_inner and do the split myself

view this post on Zulip Joel Dice (Apr 03 2025 at 15:00):

Sure. The main idea is that you might either only care about the unwritten parts or just want to clear reuse the whole buffer or both. As long as we support all those options, we should be good.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:01):

let n = buf.filled().len();
let mut buf = buf.into_inner();
buf.truncate(n);

that'd be the usage I'd imagine

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:04):

btw, any way we could integrate with std::io::Cursor here https://doc.rust-lang.org/nightly/std/io/struct.Cursor.html# ?
Does BytesBuffer do cosiderably more than std::io::Cursor<Bytes> could?

view this post on Zulip Joel Dice (Apr 03 2025 at 15:06):

Maybe I'm not quite understanding. If you start with a BytesMutBuffer with, say, 16 bytes, then you do a write, and the write delivers 7 bytes, then offset will be 7 and remaining(&self) will return 9, and (currently) into_inner will return BytesMut with all 16 bytes. So what's the purpose of your truncate call above? Do you want the result to have the first 7 bytes or the last 9 bytes?

view this post on Zulip Joel Dice (Apr 03 2025 at 15:07):

Regarding Cursor: I sort of assumed it only worked with Copy payloads, but maybe I was wrong. Let me take a closer look.

view this post on Zulip Joel Dice (Apr 03 2025 at 15:10):

I guess it doesn't matter, since Bytes is only about u8, so yes, I guess we could get rid of BytesMutBuffer and BytesBuffer in favor of Cursor<BytesMut> and Cursor<Bytes> respectively, but keep VecBuffer since it supports moving owned values, which Cursor doesn't AFAICT.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:10):

I was actually thinking about the other way round, so doing a read, I'm still getting familiar with this new API. What I need is a way to go from StreamReader<BytesBuffer> to Stream<Bytes>. It appears that naive BytesBuffer::into_inner might give more bytes than the guest might have written

view this post on Zulip Joel Dice (Apr 03 2025 at 15:12):

All BytesBuffer::into_inner would do is give you back the entire Bytes (i.e. including both the written and unwritten bytes), which is what Cursor<Bytes>::into_inner also does if I'm reading correctly.

view this post on Zulip Joel Dice (Apr 03 2025 at 15:14):

But you can always split a Bytes if you only want a subset, of course

view this post on Zulip Joel Dice (Apr 03 2025 at 15:15):

Oh, hold on. If you have a StreamReader, then you don't need to mess with BytesBuffer at all. BytesBuffer is only for writing -- it doesn't make sense for (and indeed won't work with) StreamReader.

view this post on Zulip Joel Dice (Apr 03 2025 at 15:15):

Just use StreamReader<BytesMut>.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:15):

yeah, that's what I'd guess

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:15):

Alright, this makes sense to me then

view this post on Zulip Joel Dice (Apr 03 2025 at 15:16):

er, I guess I mean StreamReader<BytesMut> since there's no way to add items to a Bytes

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:26):

If you have a moment, we could jump on a call and I could quickly show you the use case I'm working with

view this post on Zulip Joel Dice (Apr 03 2025 at 15:27):

Yup; want to send me a link?

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 15:27):

https://meet.google.com/hqc-yvwc-hgd

view this post on Zulip Joel Dice (Apr 03 2025 at 16:43):

@Roman Volosatovs : This adds an Instance::promise method for wrapping a Future in a Promise: https://github.com/bytecodealliance/wasip3-prototyping/pull/98

BTW, if all you're doing is calling Promise::into_future the then later converting that back to a Promise, you could avoid both steps and just leave it as a Promise.

This may be useful as e.g. an alternative or complement to PromisesUnordered where you want to compose some number of Promises in an async function or block with arbitrary control flow that might b...

view this post on Zulip Joel Dice (Apr 03 2025 at 16:44):

I'll start working on replacing Bytes{Mut}Buffer with Cursor<Bytes{Mut}> next

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:02):

I'd prefer leaving it as Promise, but that would prevent me from polling it multiple times in the guest task, since I have to move it to call into_future
That's the reason I'm suggesting the poll(cx, store) method on Promise, actually

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:08):

btw, impls for std::io::Cursor<impl Buf{,Mut}> could be even more useful https://docs.rs/bytes/latest/bytes/buf/trait.Buf.html https://docs.rs/bytes/latest/bytes/buf/trait.BufMut.html
and would allow using e.g. std::io::Cursor<Box<[u8]>> as a buffer passed to write

view this post on Zulip Joel Dice (Apr 03 2025 at 17:09):

I think promise.poll(cx, store) would be equivalent to doing pin!(promise.get(store)).poll(cx)

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:10):

that's what I'm doing now, but not sure if that breaks any runtime assumptions

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:10):

e.g. is this "cancel safe"?

view this post on Zulip Joel Dice (Apr 03 2025 at 17:11):

I think it should be fine; let me know if you see anything weird.
Yes, should be cancel safe, although that partly depends on the underlying Future wrapped by the Promise. All the existing public APIs that return Promises wrap cancel-safe Futures AFAIK.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:23):

if I keep the promises around, looks like I can do

pin!(store.with(|mut view| contents_rx.get(view))).poll(cx)

in guest tasks rather than using into_future

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:23):

where contents_rx is a promise

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:24):

is this a bad idea?

view this post on Zulip Joel Dice (Apr 03 2025 at 17:25):

I could also add a Promise::get_mut() -> Pin<&mut dyn Future ...> method (or something like that; not sure about the types exactly)

view this post on Zulip Joel Dice (Apr 03 2025 at 17:26):

Hmm, but then you'd have no way to feed it a store, so nevermind

view this post on Zulip Joel Dice (Apr 03 2025 at 17:27):

is this a bad idea?

Not if it works :shrug:

view this post on Zulip Joel Dice (Apr 03 2025 at 17:27):

actually, I think the borrow checker will reject it

view this post on Zulip Joel Dice (Apr 03 2025 at 17:28):

and if it doesn't then something's very wrong, because the future should close over the store ref

view this post on Zulip Joel Dice (Apr 03 2025 at 17:29):

meaning you won't be able to return the future from Accessor::with

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:31):

oh, the get also moves the Promise

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:31):

so that does not work

view this post on Zulip Joel Dice (Apr 03 2025 at 17:31):

oh, right

view this post on Zulip Joel Dice (Apr 03 2025 at 17:36):

I just realized Instance::promise will redundantly Box::pin the future you give it if it's already a Pin<Box<dyn Future>>> -- I should add a promise_from_boxed that takes an already-boxed future.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:48):

maybe it could take impl Into<Pin<Box<dyn Future>>>>?

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:48):

Also, updated the PR and ran into:

thread '<unnamed>' panicked at /Users/rvolosatovs/.cargo/git/checkouts/witx-bindgen-80318ec43c150aef/40ca9b1/crates/guest-rust/rt/src/async_support/stream_support.rs:167:9:
assertion failed: buf.remaining() == 0 || matches!(status, StreamResult::Closed)

view this post on Zulip Joel Dice (Apr 03 2025 at 17:50):

Roman Volosatovs said:

maybe it could take impl Into<Pin<Box<dyn Future>>>>?

Do arbitrary futures implement that? I want to make sure you can do e.g. let p = instance.promise(store, async move { ... });

view this post on Zulip Joel Dice (Apr 03 2025 at 17:51):

Roman Volosatovs said:

Also, updated the PR and ran into:

thread '<unnamed>' panicked at /Users/rvolosatovs/.cargo/git/checkouts/witx-bindgen-80318ec43c150aef/40ca9b1/crates/guest-rust/rt/src/async_support/stream_support.rs:167:9:
assertion failed: buf.remaining() == 0 || matches!(status, StreamResult::Closed)

If you can push what you have and tell me how to repro, I'll take a look.

view this post on Zulip Joel Dice (Apr 03 2025 at 17:52):

Joel Dice said:

Do arbitrary futures implement that? I want to make sure you can do e.g. let p = instance.promise(store, async move { ... });

Alternatively, we could just make Instance::promise require already boxed futures and make the caller box if necessary.

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:53):

yep, working on that

Joel Dice said:

Roman Volosatovs said:

maybe it could take impl Into<Pin<Box<dyn Future>>>>?

Do arbitrary futures implement that? I want to make sure you can do e.g. let p = instance.promise(store, async move { ... });

not really, there's Box -> Pin (https://doc.rust-lang.org/std/pin/struct.Pin.html#impl-From%3CBox%3CT,+A%3E%3E-for-Pin%3CBox%3CT,+A%3E%3E), which sort of helps, but given that this API is meant to be pretty low-level, I don't feel like it's an issue

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:56):

https://github.com/bytecodealliance/wasip3-prototyping/issues/100

On dffca0b cargo test -p wasmtime-wasi-http 'p3::outgoing::http_0_3_outbound_request_large_post' panics with: thread '<unnamed>' panicked at /Users/rvolosatovs/.cargo/git/checkouts/witx-bindgen-803...

view this post on Zulip Joel Dice (Apr 03 2025 at 17:57):

Almost done with the Cursor PR, will debug #100 after that

view this post on Zulip Roman Volosatovs (Apr 03 2025 at 17:58):

awesome, thank you!

view this post on Zulip Joel Dice (Apr 03 2025 at 18:21):

Just pushed the Cursor PR; taking a break for lunch, but will take a look at #100 after that if @Alex Crichton hasn't already figured it out.

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 10:45):

@Joel Dice if I were to construct a Promise using Instance::promise, am I right in assuming that I can use Promise::into_future inside the future I passed to Instance::promise? (since it's running inside a Promise)

view this post on Zulip Joel Dice (Apr 04 2025 at 12:01):

Yes, correct. I started adding more docs with examples yesterday. I'll push a PR with those today.

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 13:09):

Awesome, I used that trick to get the incoming HTTP working https://github.com/bytecodealliance/wasip3-prototyping/pull/58/commits/d4c69cf62ab83117f7a5cce684f03942b1050f2e

I also reworked the API a bit after our discussion, now everything is promise-based, so it's up to the caller to figure out how to poll it, meaning multiple concurrent calls are possible using the same store, while still getting back a fully-compliant http_body::Body, e.g. for a single call https://github.com/bytecodealliance/wasip3-prototyping/blob/d4c69cf62ab83117f7a5cce684f03942b1050f2e/crates/wasi-http/tests/all/p3/mod.rs#L183-L207
So the actual store is never moved

Implementation of WebAssembly/wasi-http#162
Fork of wasmtime for protoyping WASIp3 work and coordination, not intended for any production use case, purely for development - bytecodealliance/wasip3-prototyping

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 15:19):

And we have an HTTP roundtrip :) https://github.com/rvolosatovs/p3-http-test

using wasmtime from https://github.com/bytecodealliance/wasip3-prototyping/pull/58 + https://github.com/bytecodealliance/wasip3-prototyping/commit/b007214c67243d00078b444937562c2413664eb0 applied on top

`wasi:http@0.3.0` demo. Contribute to rvolosatovs/p3-http-test development by creating an account on GitHub.
Implementation of WebAssembly/wasi-http#162 With Wasmtime binary built from this PR with this patch applied: b007214 (from #60), I have the complete round trip working using components in https://g...
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 15:54):

I'm marking https://github.com/bytecodealliance/wasip3-prototyping/pull/58 ready for review, since it grew pretty big at this point, I feel like we(I) can continue porting the rest of incoming HTTP tests etc in follow-ups

Implementation of WebAssembly/wasi-http#162 With Wasmtime binary built from this PR with this patch applied: b007214 (from #60), I have the complete round trip working using components in https://g...

view this post on Zulip Joel Dice (Apr 04 2025 at 16:13):

Awesome! Yeah, it will be great to get that merged finally so we're not juggling branches a rebasing so much. I'll take a look today.

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 18:41):

any idea what this could mean https://github.com/bytecodealliance/wasip3-prototyping/issues/105 ?

Not really sure how to debug this, when trying to merge #58 , tests on riscv64 panic with: failures: ---- p3::outgoing::http_0_3_outbound_request_invalid_header stdout ---- thread 'p3::outgoing::ht...

view this post on Zulip Joel Dice (Apr 04 2025 at 18:43):

I saw that, and I'm as mystified as you. @Alex Crichton have you seen anything like that before (i.e. assert_eq! failing for integer values but then printing an error message that they're the same)?

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:44):

hm no I've not seen that before

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:44):

my first guess though is some sort of memory corruption

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:44):

where it's not-equal during the compare but equal by the time the print happens

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:44):

in theory also UB where the compare is optimized to always false for some UB reason but then the print actually shows they're equal

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:45):

riscv64 is optimized where my guess is none of us have been optimizing locally

view this post on Zulip Joel Dice (Apr 04 2025 at 18:46):

@Roman Volosatovs have you tried running those tests locally with cargo test --release by any chance?

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 18:48):

I haven't, trying it now

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 18:50):

Succeeded on aarch64-darwin

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 18:51):

I can try x86_64-linux later tonight as well

view this post on Zulip Roman Volosatovs (Apr 04 2025 at 18:52):

Feels like maybe the right thing to do is run these in qemu to see if it's riscv64 specific

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:52):

there's always the possibility of qemu bugs as well yeah

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:58):

also FYI I'm going to try an attempt with merge now

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:58):

we're... extremely far behind

view this post on Zulip Alex Crichton (Apr 04 2025 at 18:58):

and the conflict is massive

view this post on Zulip Alex Crichton (Apr 04 2025 at 20:24):

I'm switching the p3-prototyping repo to use merge commits instead of squash, I think squashing is making merging with main worse

view this post on Zulip Roman Volosatovs (Apr 07 2025 at 12:35):

still running into the same bug on riscv64 after rebase, so I ignored these tests on riscv64 for now https://github.com/bytecodealliance/wasip3-prototyping/pull/58/commits/5e8f880803098f244ef000297ec03f7151d22e01

Implementation of WebAssembly/wasi-http#162 With Wasmtime binary built from this PR with this patch applied: b007214 (from #60), I have the complete round trip working using components in https://g...

view this post on Zulip Joel Dice (Apr 07 2025 at 13:31):

Ok, I'll get QEMU set up and see if I can learn anything.

view this post on Zulip Joel Dice (Apr 07 2025 at 14:58):

I just ran the tests on main using cargo test -p wasmtime-wasi-http --test all --target riscv64gc-unknown-linux-gnu --release with QEMU 9.1.2 after removing all the ignore attributes from the http_0_3_* tests and they all passed. Am I doing something wrong?

view this post on Zulip Alex Crichton (Apr 07 2025 at 14:59):

try this: CARGO_INCREMENTAL=0 CARGO_PROFILE_DEV_DEBUG=0 CARGO_PROFILE_TEST_DEBUG=0 CARGO_PROFILE_DEV_OPT_LEVEL=2 WASMTIME_TEST_NO_HOG_MEMORY=1 cargo test -p wasmtime-wasi-http --test all --target riscv64gc-unknown-linux-gnu p3::outgoing::http_0_3_outbound_request_invalid_header

view this post on Zulip Joel Dice (Apr 07 2025 at 15:01):

That worked (i.e. the test failed). Thanks!

view this post on Zulip Roman Volosatovs (Apr 07 2025 at 15:01):

just a small note that if you rebase on latest main, the test will be called p3::outgoing::p3_http_outbound_request_invalid_header

view this post on Zulip Victor Adossi (Apr 07 2025 at 16:32):

Notes from the meeting this week:

P3 sync meeting for 2025/04/07

Implementation of WebAssembly/wasi-http#162 With Wasmtime binary built from this PR with this patch applied: b007214 (from #60), I have the complete round trip working using components in https://g...

view this post on Zulip Joel Dice (Apr 07 2025 at 17:34):

For the record: the riscv64 failure appears to be a pre-existing Cranelift codegen bug; @Alex Crichton is going to investigate further.

view this post on Zulip Alex Crichton (Apr 07 2025 at 17:37):

ok yeah I've fixed this locally now

view this post on Zulip Dave Bakker (badeend) (Apr 07 2025 at 20:20):

I wasn't present during this meeting, so I'll be extrapolating purely based on the notes. The following cherry picked items resonated with me:

Alex: There aren't enough maintainers for wasi-libc

Alex: the main problem is not many people want to write C

Victor: Why is wasi-libc not a Rust thing?

Alex: Easiest option was Musl compiled to wasi. Only I/O system layer is what we have to maintain -- very different from having to maintain 100% of the libc

I am not much a C developer either. I've only worked on wasi-libc during the initial implementation of wasi-sockets together with Joel, but I wouldn't describe my time working on wasi-libc as "fun". To the point that I dread working on it again, despite the socket work not being complete. :neutral: To make things worse, once shared-everything-threading becomes a thing, I suspect wasi-libc will start breaking left and right because I'm not confident at all that what I wrote is thread safe.

I realize there's a lot of value in continuing off the work provided by MUSL. So I wonder if there's another middle ground here where e.g. we keep using MUSL for pretty much everything, but write the POSIX<->WASI IO interop layer in a statically linked Rust library, similar to the p1-to-p2 adapter.


Joel: (...) is the suggestion that they need to decide they're going all-in on POSIX (& base on wasi-sockets) or go all-in on WASI HTTP (& do socket stuff without wasi-libc)? i.e. all in on native wasi or POSIX, but not mix?

Alex: Essentially yes, it's probably a bad idea to support a mix

I worry this all-or-nothing approach will be a tough pill to swallow for language/framework authors. But I'm fine deferring this until real world users come knocking

view this post on Zulip Pat Hickey (Apr 07 2025 at 20:30):

std will probably link against wasi-libc forever, because its expected for C library interop, even if nothing in std strictly needs to use it

view this post on Zulip Alex Crichton (Apr 07 2025 at 20:31):

AFAIK many folks are in a similar boat of "would be nice to write I/O stuff in rust". I don't think there's 100% alignment amongst all stakeholders but tbh there aren't that many super active stakeholders to begin with anyway, so I don't think it would necessarily require tons of buy-in.

Otherwise for mixing things and posix-vs-wasi it's probably best to discuss in the context of possible additions to wasi-libc. My high-level goal is to avoid any one particular language/runtime leaking into wasi-libc, e.g. taking everything needed by Python and putting it in wasi-libc when something like rust's libstd wouldn't want it at all. How exactly to achieve that high level goal without Python rewriting wasi-libc is going to be a balancing act and I agree the goal is for Python and Rust, for example, to uset he same wasi-libc

view this post on Zulip Pat Hickey (Apr 07 2025 at 20:31):

also, we're working on hiring a contractor specifically to help us with wasi-libc

view this post on Zulip Alex Crichton (Apr 07 2025 at 20:32):

Pat Hickey said:

std will probably link against wasi-libc forever, because its expected for C library interop, even if nothing in std strictly needs to use it

I may be misinterpreting Dave but my read is that we'd in theory rewrite parts of wasi-libc in Rust rather than having everything in C, specifically the non-musl portions in Rust

view this post on Zulip Alex Crichton (Apr 07 2025 at 20:32):

(but rust would still use wasi-libc)

view this post on Zulip Pat Hickey (Apr 07 2025 at 20:32):

ah ok sorry i misread that as being just some separate rust code from wasi-libc itself

view this post on Zulip Joel Dice (Apr 07 2025 at 20:39):

Otherwise for mixing things and posix-vs-wasi it's probably best to discuss in the context of possible additions to wasi-libc.

What I've been envisioning is public APIs which allow code built on wasi-libc to access (and optionally swap out) the WASI-level resource(s), streams, etc. corresponding to a file descriptor. That would include taking ownership of the WASI-level handles by removing the descriptor entirely and also doing the opposite: giving wasi-libc ownership of WASI-level handles and getting a new descriptor back for them.

view this post on Zulip Dave Bakker (badeend) (Apr 07 2025 at 20:49):

I may be misinterpreting Dave but my read is that we'd in theory rewrite parts of wasi-libc in Rust rather than having everything in C, specifically the non-musl portions in Rust

That's indeed what I meant. :+1: The periphery of such a Rust library would still be rather C-esque of course, but me personally would still be more comfortable maintaining awkward looking Rust compared to the C implementation. Though I might be biased towards Rust :melting_face:

view this post on Zulip Dave Bakker (badeend) (Apr 07 2025 at 20:59):

My high-level goal is to avoid any one particular language/runtime leaking into wasi-libc

Agree :+1:


Last updated: Apr 07 2025 at 21:03 UTC