Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wasm32-wasi target support #4716

Merged
merged 8 commits into from
Jul 12, 2022
Merged

Wasm32-wasi target support #4716

merged 8 commits into from
Jul 12, 2022

Conversation

rjzak
Copy link
Contributor

@rjzak rjzak commented May 24, 2022

Motivation

Getting Tokio working on WebAssembly-WASI so that web applications can be executed by a Wasi runtime, such as Wasmtime and others.

Solution

Working on supporting the wasm32-wasi target. The use of Tokio with WebAssembly should be seamless and easy to the extent possible. Companion to tokio-rs/mio#1576.

Testing

Signed-off-by: Richard Zak richard@profian.com

@carllerche
Copy link
Member

Could you include the output you get? Ideally w/ a full backtrace?

@rjzak
Copy link
Contributor Author

rjzak commented May 24, 2022

I'm not sure how to get a full stack trace, but this is the output where a connection with nc is made after "Listening" displays.

Listening.
Error: Error { kind: Unsupported, message: "operation not supported on this platform" }
Error: Exited with i32 exit status 1

@Darksonn Darksonn added the A-tokio Area: The main tokio crate label May 25, 2022
@carllerche
Copy link
Member

It looks like a specific function call is returning an error, could you identify which one it is? You can add logging even if just temporary inside your app / tokio.

@rjzak
Copy link
Contributor Author

rjzak commented May 25, 2022

Two things:

  1. I set the target toolchain to nightly, and further progress was made. Now the Wasm binary is able to receive connections. However, it doesn't respond.
  2. I did add the print statements to track execution, as suggested.
Listening.
Tokio TcpListener::accept() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:161
Tokio Registration::async_io() /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:250
Tokio Registration::async_io() self.readiness(READABLE) = ReadyEvent { tick: 1, ready: Ready { is_readable: true, is_writable: false, is_read_closed: true, is_write_closed: false } } returned @ /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:253
wasi::accept() /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:32
wasi::accept() listener.accept() OK /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:34
wasi::accept() stream.set_nonblocking(true) /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:36
Tokio TcpListener::accept() self.io.registration().async_io().await /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:167
Tokio TcpListener::accept() TcpStream::new() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:169
Connection received.
Tokio TcpListener::accept() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:161
Tokio Registration::async_io() /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:250
Tokio Registration::async_io() self.readiness(READABLE) = ReadyEvent { tick: 1, ready: Ready { is_readable: true, is_writable: false, is_read_closed: false, is_write_closed: false } } returned @ /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:253
wasi::accept() /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:32

What seems to be missing is writing the response data to the stream to send back to the client. Does work as a native Linux binary, so I'm probably just missing something...

@rjzak
Copy link
Contributor Author

rjzak commented May 25, 2022

Tokio side, trying to read the contents early, I'm getting "operation not supported" when trying to peek(), and "operation would block" when trying to try_read(). What's the best way to read early on the Tokio side? The socket is already set to allow blocking I/O explicitly on the Wasi side https://github.com/tokio-rs/mio/blob/master/src/sys/wasi/mod.rs#L33.

Listening.
Tokio TcpListener::accept() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:161
Tokio Registration::async_io() /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:250
Tokio Registration::async_io() self.readiness(READABLE) = ReadyEvent { tick: 1, ready: Ready { is_readable: true, is_writable: false, is_read_closed: true, is_write_closed: false } } returned @ /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:253
wasi::accept() /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:32
wasi::accept() listener.accept() OK /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:34
wasi::accept() stream.set_nonblocking(true) /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:36
Tokio TcpListener::accept() self.io.registration().async_io().await /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:167
Tokio TcpListener::accept() error operation not supported on this platform trying to peek() at the buffer /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:175
Tokio TcpListener::accept() error operation would block trying to TcpStream::try_read() at the buffer /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:185
Tokio TcpListener::accept() TcpStream::new() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:188
Connection received.
Tokio TcpListener::accept() /home/rjzak/CLionProjects/tokio/tokio/src/net/tcp/listener.rs:161
Tokio Registration::async_io() /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:250
Tokio Registration::async_io() self.readiness(READABLE) = ReadyEvent { tick: 1, ready: Ready { is_readable: true, is_writable: false, is_read_closed: false, is_write_closed: false } } returned @ /home/rjzak/CLionProjects/tokio/tokio/src/io/driver/registration.rs:253
wasi::accept() /home/rjzak/CLionProjects/mio/src/sys/wasi/mod.rs:32

@rjzak
Copy link
Contributor Author

rjzak commented May 25, 2022

After disabling tokio::spawn(), the echo server example works! I need to figure out the implications here. https://github.com/rjzak/tokio-echo-test/blob/main/src/main.rs#L65

@alsuren alsuren mentioned this pull request May 29, 2022
@rjzak rjzak changed the title Wasm Improvements WiP Wasm32-wasi target support Jun 3, 2022
@rjzak rjzak force-pushed the wasi_wip branch 8 times, most recently from a55272a to 858215f Compare June 6, 2022 15:47
@rjzak rjzak marked this pull request as ready for review June 6, 2022 15:47
@rjzak rjzak force-pushed the wasi_wip branch 7 times, most recently from e81f58e to 95fcfa7 Compare June 6, 2022 19:57
@rjzak rjzak force-pushed the wasi_wip branch 3 times, most recently from 93fd946 to d8ab434 Compare July 11, 2022 21:07
Signed-off-by: Richard Zak <richard@profian.com>
@rjzak rjzak force-pushed the wasi_wip branch 2 times, most recently from 0179a4c to 4c0cf30 Compare July 11, 2022 22:32
Signed-off-by: Richard Zak <richard@profian.com>
@carllerche carllerche mentioned this pull request Jul 12, 2022
6 tasks
Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

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

I would like to have a release before I click the merge button, but I believe this PR is ready as-is.

@carllerche carllerche merged commit 6d3f92d into tokio-rs:master Jul 12, 2022
@CryZe
Copy link

CryZe commented Jul 12, 2022

Wish I had seen this earlier. target_family = "wasm" is preferred over checking for wasm32 to be forwards compatible with wasm64.

@Darksonn
Copy link
Contributor

Darksonn commented Jul 12, 2022

Can you please comment that on the meta issue mentioned above? Edit: I've added it myself.

@rjzak rjzak deleted the wasi_wip branch July 13, 2022 04:02
@izissise
Copy link

Hello, I'm trying to run the first example rjzak/tokio-echo-test but I'm getting this error
error: Only features sync,macros,io-util,rt are supported on wasm.

How can one uses net io with wasi?

@Darksonn
Copy link
Contributor

It's unstable. You need to enable the tokio_unstable flag to use it. You can read how to do that here.

@rjzak
Copy link
Contributor Author

rjzak commented Jul 21, 2022

@izissise Thanks for pointing this out, I updated the readme on that example project.

@Darksonn Darksonn added the T-wasm Topic: Web Assembly label Jul 25, 2022
@AshleySetter
Copy link

AshleySetter commented Aug 9, 2022

@rjzak I was trying to build your example at https://github.com/rjzak/tokio-echo-test but I'm a relative beginner at rust and I was met with an error I couldn't resolve, any help would be much appreciated.

RUSTFLAGS="--cfg tokio_unstable" cargo build --target=wasm32-wasi
    Updating git repository `https://github.com/rjzak/tokio`
error: failed to get `tokio` as a dependency of package `tokio-echo-test v0.0.1 (/home/ash/Documents/Junk/tokio-echo-test)`

Caused by:
  failed to load source for dependency `tokio`

Caused by:
  Unable to update https://github.com/rjzak/tokio?branch=wasi_wip#9dfcecbd

Caused by:
  object not found - no match for id (9dfcecbdc71c8403125df1271ebdc2ea79f659e2); class=Odb (9); code=NotFound (-3)

@rjzak
Copy link
Contributor Author

rjzak commented Aug 9, 2022

Hello! The Git branch wasi_wip was deleted when this PR was merged, so change Cargo.toml to point to tokio-rs/tokio instead of rjzak, and set branch = "master".

@AshleySetter
Copy link

@rjzak Brilliant, thanks, that works.

Is that the same for https://github.com/rjzak/axum-wasm-test as well? Which git repo and branch of axum should be used with that demo?

@rjzak
Copy link
Contributor Author

rjzak commented Aug 9, 2022

Yes, and I'm working on fixing some things up. I noticed that the latest Tokio release don't block socket2 when compiling for Wasi, but is fixed in a later commit b2ada60. So for the time being, Tokio should be pulled in with git = "https://www.github.com/tokio-rs/tokio", rev = "b2ada60" or git = "https://www.github.com/tokio-rs/tokio", branch = "master"

crapStone pushed a commit to Calciumdibromid/CaBr2 that referenced this pull request Sep 11, 2022
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dependencies | minor | `1.20.1` -> `1.21.0` |
| [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dev-dependencies | minor | `1.20.1` -> `1.21.0` |

---

### Release Notes

<details>
<summary>tokio-rs/tokio</summary>

### [`v1.21.0`](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.21.0)

[Compare Source](tokio-rs/tokio@tokio-1.20.1...tokio-1.21.0)

##### 1.21.0 (September 2, 2022)

This release is the first release of Tokio to intentionally support WASM. The `sync,macros,io-util,rt,time` features are stabilized on WASM. Additionally the wasm32-wasi target is given unstable support for the `net` feature.

##### Added

-   net: add `device` and `bind_device` methods to TCP/UDP sockets ([#&#8203;4882])
-   net: add `tos` and `set_tos` methods to TCP and UDP sockets ([#&#8203;4877])
-   net: add security flags to named pipe `ServerOptions` ([#&#8203;4845])
-   signal: add more windows signal handlers ([#&#8203;4924])
-   sync: add `mpsc::Sender::max_capacity` method ([#&#8203;4904])
-   sync: implement Weak version of `mpsc::Sender` ([#&#8203;4595])
-   task: add `LocalSet::enter` ([#&#8203;4765])
-   task: stabilize `JoinSet` and `AbortHandle` ([#&#8203;4920])
-   tokio: add `track_caller` to public APIs ([#&#8203;4805], [#&#8203;4848], [#&#8203;4852])
-   wasm: initial support for `wasm32-wasi` target ([#&#8203;4716])

##### Fixed

-   miri: improve miri compatibility by avoiding temporary references in `linked_list::Link` impls ([#&#8203;4841])
-   signal: don't register write interest on signal pipe ([#&#8203;4898])
-   sync: add `#[must_use]` to lock guards ([#&#8203;4886])
-   sync: fix hang when calling `recv` on closed and reopened broadcast channel ([#&#8203;4867])
-   task: propagate attributes on task-locals ([#&#8203;4837])

##### Changed

-   fs: change panic to error in `File::start_seek` ([#&#8203;4897])
-   io: reduce syscalls in `poll_read` ([#&#8203;4840])
-   process: use blocking threadpool for child stdio I/O ([#&#8203;4824])
-   signal: make `SignalKind` methods const ([#&#8203;4956])

##### Internal changes

-   rt: extract `basic_scheduler::Config` ([#&#8203;4935])
-   rt: move I/O driver into `runtime` module ([#&#8203;4942])
-   rt: rename internal scheduler types ([#&#8203;4945])

##### Documented

-   chore: fix typos and grammar ([#&#8203;4858], [#&#8203;4894], [#&#8203;4928])
-   io: fix typo in `AsyncSeekExt::rewind` docs ([#&#8203;4893])
-   net: add documentation to `try_read()` for zero-length buffers ([#&#8203;4937])
-   runtime: remove incorrect panic section for `Builder::worker_threads` ([#&#8203;4849])
-   sync: doc of `watch::Sender::send` improved ([#&#8203;4959])
-   task: add cancel safety docs to `JoinHandle` ([#&#8203;4901])
-   task: expand on cancellation of `spawn_blocking` ([#&#8203;4811])
-   time: clarify that the first tick of `Interval::tick` happens immediately ([#&#8203;4951])

##### Unstable

-   rt: add unstable option to disable the LIFO slot ([#&#8203;4936])
-   task: fix incorrect signature in `Builder::spawn_on` ([#&#8203;4953])
-   task: make `task::Builder::spawn*` methods fallible ([#&#8203;4823])

[#&#8203;4595]: tokio-rs/tokio#4595

[#&#8203;4716]: tokio-rs/tokio#4716

[#&#8203;4765]: tokio-rs/tokio#4765

[#&#8203;4805]: tokio-rs/tokio#4805

[#&#8203;4811]: tokio-rs/tokio#4811

[#&#8203;4823]: tokio-rs/tokio#4823

[#&#8203;4824]: tokio-rs/tokio#4824

[#&#8203;4837]: tokio-rs/tokio#4837

[#&#8203;4840]: tokio-rs/tokio#4840

[#&#8203;4841]: tokio-rs/tokio#4841

[#&#8203;4845]: tokio-rs/tokio#4845

[#&#8203;4848]: tokio-rs/tokio#4848

[#&#8203;4849]: tokio-rs/tokio#4849

[#&#8203;4852]: tokio-rs/tokio#4852

[#&#8203;4858]: tokio-rs/tokio#4858

[#&#8203;4867]: tokio-rs/tokio#4867

[#&#8203;4877]: tokio-rs/tokio#4877

[#&#8203;4882]: tokio-rs/tokio#4882

[#&#8203;4886]: tokio-rs/tokio#4886

[#&#8203;4893]: tokio-rs/tokio#4893

[#&#8203;4894]: tokio-rs/tokio#4894

[#&#8203;4897]: tokio-rs/tokio#4897

[#&#8203;4898]: tokio-rs/tokio#4898

[#&#8203;4901]: tokio-rs/tokio#4901

[#&#8203;4904]: tokio-rs/tokio#4904

[#&#8203;4920]: tokio-rs/tokio#4920

[#&#8203;4924]: tokio-rs/tokio#4924

[#&#8203;4928]: tokio-rs/tokio#4928

[#&#8203;4935]: tokio-rs/tokio#4935

[#&#8203;4936]: tokio-rs/tokio#4936

[#&#8203;4937]: tokio-rs/tokio#4937

[#&#8203;4942]: tokio-rs/tokio#4942

[#&#8203;4945]: tokio-rs/tokio#4945

[#&#8203;4951]: tokio-rs/tokio#4951

[#&#8203;4953]: tokio-rs/tokio#4953

[#&#8203;4956]: tokio-rs/tokio#4956

[#&#8203;4959]: tokio-rs/tokio#4959

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzMi4xODcuMCIsInVwZGF0ZWRJblZlciI6IjMyLjE4Ny4wIn0=-->

Co-authored-by: cabr2-bot <cabr2.help@gmail.com>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1532
Reviewed-by: crapStone <crapstone@noreply.codeberg.org>
Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate R-loom Run loom tests on this PR T-wasm Topic: Web Assembly
Projects
None yet
Development

Successfully merging this pull request may close these issues.