hey there, I am wondering if there are any progress on preview2 support in wasi-libc? Related issue: https://github.com/WebAssembly/wasi-libc/issues/430
Out of curiosity, is that blocking something you're working on or planning to work on? I.e. is there some Preview 2 feature that you can't use ergonomically with the existing wasi-libc + adapter approach? If the answer is "network sockets", I'm planning to start working on that soon-ish. If the answer is something else, I'd be interested to know.
We were disucssing wasi-libc preview2 support in today's Go subgroup meeting and this idea came out when we were thinking whether TinyGo preview2 support needs to rely on wasi-libc or not. Currently we don't have a firm answer on that, but we are leaning towards no wasi-libc dependency.
is that blocking something you're working on or planning to work on?
No, the existing wasi-libc and adapter approach would totally work.
There are still advantages on preview2 support in wasi-libc though. One of them is that we hypothethized that it will reduce the component size by removing the adapter in the component.
I was able to modify the adapter to directly link with my code, creating a preview2 native module from c++ sources. I will try to upload the necessary changes to a public github over the weekend so that you can take a look.
Christof Petig said:
I was able to modify the adapter to directly link with my code, creating a preview2 native module from c++ sources. I will try to upload the necessary changes to a public github over the weekend so that you can take a look.
I uploaded a less intrusive version of the patch to https://github.com/cpetig/wasmtime-adapter - but so far I was unable to test it, because wasmtime doesn't yet implement all of the preview2 interfaces used by the adapter. I will give it another try with jco, but that will take time.
Ideally this adapter would consist of multiple (object) files, so that only used interfaces are required. wasm-opt (binaryen) can reduce unused dependencies for now.
because wasmtime doesn't yet implement all of the preview2 interfaces used by the adapter.
not sure what this means - wasmtime-wasi does have an implementation of all the interfaces used by the adapter, maybe you need to add them to your linker? or is there some other unresolved symbols related to your build?
The resulting binary is importing filesystem preopens and terminal input/output streams which I didn't see in the Wasi implementations of wasmtime, so I assumed that they are yet to be implemented. I can take a closer look and send the exact interface names later.
https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi-preview1-component-adapter/src/descriptors.rs#L184 refers to preopens, but I don't see that in https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi/src/preview2/mod.rs#L83
The host implementation of wasi:filesystem/preopens@0.2.0-rc-2023-11-05#get-directories
is here: https://github.com/bytecodealliance/wasmtime/blob/24d945f3e34e3c24e0160850bb3f668c0eeabec4/crates/wasi/src/preview2/host/filesystem.rs#L15-L29
Thank you, but I couldn't find the registration of the implementation under that name, so I assumed it would be missing :thinking:
wasmtime-wit-bindgen
generates the code that does the registration. Specifically, it will generate an add_to_linker
function which adds all the host functions and types to the wasmtime::component::Linker
, thereby making them available to any guests instantiated using that Linker
. In this case, wasmtime_wasi::preview2::command::add_to_linker
should provide the wasi:filesystem/preopens@0.2.0-rc-2023-11-05#get-directories
function along with everything else the adapter might need.
That makes sense, I will take a closer look to why wasmtime -S preview2 mybinary.wasm complains about the preopens missing.
Do make sure the version of wasmtime
you're using matches the adapter (i.e. if you're using and adapter that targets WASI 0.2.0-rc-2023-10-18, you'll want Wasmtime 14.0.x). Note that 0.2.0-rc-2023-11-05 is particularly tricky since there is a range of commits in the wasmtime repo that use that version such that the WIT files changed over time in incompatible ways. Your best bet is to build the adapter and wasmtime
command from the exact same commit.
Joel Dice said:
Out of curiosity, is that blocking something you're working on or planning to work on? I.e. is there some Preview 2 feature that you can't use ergonomically with the existing wasi-libc + adapter approach? If the answer is "network sockets", I'm planning to start working on that soon-ish. If the answer is something else, I'd be interested to know.
We're a wish to move socket based WAMR applications to Wasmtime and get them to work without modification. So, it's wasi-preview-1 + WAMR sockets, running on wasi-preview-2 + some sort of adapter.
Of course, since there was no socket standard for preview-1, we've portability issues moving forward. (yay!).
Thanks a lot to Joel and Pat for insisting that wasmtime supports all necessary preview2 symbols, I just found out that once I create a component out of my module it works (with -Wcomponent-model -Spreview2) - of course, because the resulting module targets already preview2, no adapter is needed.
Also I just uploaded the successfully tested static adapter libraries as releases https://github.com/cpetig/wasmtime-adapter/releases/tag/2023-11-15
If the answer is "network sockets", I'm planning to start working on that soon-ish.
@Joel Dice, let me know if there's anything I can do to help.
Thanks. I was hoping to start this week, but got busy with other things, so it will probably be next week.
Christof Petig said:
Also I just uploaded the successfully tested static adapter libraries as releases
er sorry hit enter too soon, but Christof if you're interested I think that'd be neat to add to Wasmtime's CI and get releases for each version of Wasmtime as well
e.g. having a new build mode of the adapter which produces a *.a
instead of a *.wasm
Well, it clearly solves a problem for me (wanting to combine wamr with WIT), but the solution doesn't feel clean enough to me, yet.
Ideally you would have a feature selecting between the modes to build both variants from the same source code, and you probably want to cut the single adapter object file into one per feature or interface - although link time optimization seems to remove all the unused preview1 implementations quite well.
I would like to receive some feed back from users before going this step.
ok makes sense, but the design of a standalone *.wasm
was primarily intended to ease the transition into preview2, and having alternative stepping stones I think is useful too
Couple of updates on wasi-libc
support for Preview 2 (including wasi-sockets
):
wasi-libc
, Rust std
, mio
and tokio
. At this point, you can make outbound IPv4 or IPv6 TCP connections in C or Rust, synchronously or asynchronously.Awesome!
I see you're targeting 0.2.0-rc-2023-10-18
. Just a heads up; 0.2.0-rc-2023-11-10
has some notable changes in the UDP spec.
How can I get your branch running?
I have:
/wasi-sdk-20.0
https://github.com/dicej/wasi-libc/tree/sockets
into /wasi-libc
make CC=/wasi-sdk-20.0/bin/clang AR=/wasi-sdk-20.0/bin/llvm-ar NM=/wasi-sdk-20.0/bin/llvm-nm
/wasi-sdk-20.0/bin/clang --sysroot=/wasi-libc/sysroot program.c -o program.wasm
Program.c:
#include <stdio.h>
#include <sys/socket.h>
int main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
printf("Error while creating socket\n");
return -1;
}
printf("Yay!\n");
return 0;
}
But I still get the error:
program.c:5:13: error: call to undeclared function 'socket';
this is amazing work, @Joel Dice. We have several groups over here that are needing wasi-libc work and willing to dive in to help -- but do not know where to start. I think I need to help various people engage in a constructive way and not chaos-inducing way. :-)
But I still get the error
Nevermind. Turns out the socket functions weren't being exported in socket.h
yet. I've got it working now :working_on_it:
Badeend said:
But I still get the error
Nevermind. Turns out the socket functions weren't being exported in
socket.h
yet. I've got it working now :working_on_it:
Good catch. I'll admit I've only been testing with Rust so far, so I've probably missed a few basic things on the C side.
Ralph said:
this is amazing work, Joel Dice. We have several groups over here that are needing wasi-libc work and willing to dive in to help -- but do not know where to start. I think I need to help various people engage in a constructive way and not chaos-inducing way. :-)
Sounds great. I'd be happy to help coordinate efforts and e.g. schedule a meeting to divy up work as appropriate.
I chatted with Till about ways to help others contribute to the wasi-libc/wasi-sockets effort, and we agreed that making one or issues in the GitHub, each with task checklists (like what Yosh has done for Jco, e.g. https://github.com/bytecodealliance/jco/issues/207) would great. Maybe one issue each for TCP, UDP, and DNS? I'll take a stab at it when I get a chance, although I may need help from e.g. @Badeend to ensure it's complete.
we agreed that making one or issues in the GitHub, each with task checklists (...)
We have several groups (...) willing to dive in to help
That's great! TBH, I don't think there's _that_ much work to be done :stuck_out_tongue: It seems to me that having one or two people working on it for a few days could get it pretty far already.
And if it wasn't clear already; I'm definitely up for being one of those people. :octopus:
It's one of my objectives to find some help here. good chance, given the timing, that help is found after Jan 1.....
@Joel Dice I've just submitted a PR to your branch expanding TCP support even further
https://github.com/dicej/wasi-libc/pull/1
The TCP support may 100% complete yet (see summary in PR), but I consider it "good enough" for a one-weekend project.
Works On My Machine™
drive-by comment but some of those names are super long so I've opened https://github.com/bytecodealliance/wit-bindgen/pull/783 to enable reducing some of the verbosity in the C bindings here
nice
@Badeend Thanks so much for working on this; I'm 2/3 through reviewing your PR amidst a barrage of meetings.
@Badeend FYI, I'm working on adding ioctl
and poll
support for wasi-sockets
in wasi-libc
(in case you were planning to do the same). Trying to get a Python asyncio
test passing.
Great! I'm working on UDP, so no conflict there :+1:
I pushed ioctl
and poll
support yesterday. Python is working nicely: https://github.com/dicej/wasi-sockets-tests/blob/main/client-python/app.py
The next big thing I plan to work on is to build separate sysroots for wasm32-wasi
(Preview 1) and wasm32-wasi-preview2
and update wasi-sdk
to build and test both of them (using wit-component
for the latter). Once that's done, I'd like to get a draft PR up for wasi-libc
to start getting feedback, even if not everything is implemented yet.
y'all doing yeoperson's work here.....
Initial UDP implementation is ready: https://github.com/dicej/wasi-libc/pull/4
@Badeend I just pushed https://github.com/dicej/wasi-libc/commit/6be1e1a29cfb1d1224b9a5a940de48ff26699a23 and https://github.com/dicej/wasi-sdk/commit/f9dabc8322dfa9cd9a717bf5fccd3116e86938f6, which separate the Preview 1 and Preview 2 builds. I'm going to try to keep both of them working going forward and will work on enabling CI testing for both tomorrow. Note the use of the new __wasilibc_use_preview2
preprocessor directive to conditionally enable Preview 2 features.
Great!
@Dave Bakker (badeend) I've been running the socket tests in the CPython regression test suite to test our wasi-libc
work. There are a lot of failures, but most of them are due to lack of thread, process, signal, and unix domain socket support, all of which are out of scope for what we're doing. I'm currently digging into the remaining failures which aren't immediately obvious.
Some of the failures are due to neither SO_BROADCAST
nor SO_REUSEADDR
existing. Are either of those in scope for wasi-sockets
(or for emulation in wasi-libc
)?
It Depends™:
I think we should define SO_REUSEADDR and implement it in libc for TCP as a no-op. As for SO_BROADCAST: is it actually being used, or does it just need the constant to be defined? Maybe the simplest solution would be to define all commonly used sockopt constants, even if they're not implemented.
This is the SO_BROADCAST
test: https://github.com/dicej/cpython/blob/abfbab6415fb029e7dca19ecc8d29a13da37bf71/Lib/test/test_asyncio/test_base_events.py#L1652-L1667. Looks like the test just verifies that SO_BROADCAST
can be get and set via getsockopt
/setsockopt
. To be clear: we don't need the test to pass if it's not in scope (yet).
Thanks for the info regarding SO_REUSEADDR
. I'll go ahead and add it as a no-op.
UDP broadcast and multicast are not part of preview2, so those tests will most likely fail.
Interesting testsuite, BTW. I'm curious how many preview2 can pass
I've got all the relevant CPython asyncio regression tests passing (i.e. the ones that don't require multithreading, process spawning, signals, broadcast, etc.). :tada:
Awesome! :rocket:
Last updated: Dec 23 2024 at 12:05 UTC