Closed avahahn closed 2 months ago
Dockerfiles & packaging need to be adapted for this change, indeed.
There's a little too much going on in this commit.
Can you extract the wasm-wasi-component changes into their own commit please. That's the important thing to get merged.
This now only contains the wasm-wasi-component changes
Testing it out...
Hmm, where to start!
So firstly I tried some of my C based wasi-http 0.2.0 components with this updated module but that resulted in failure, one using the reactor adaptor wouldn't load, the other using the proxy adaptor loaded, but errors out on requests.
Even after updating all the things; wit-bindgen, wasm-tools, wasi-http, same result... OK lets forget that for now. There are so many moving parts and everything seems to be in a continual state of flux...
So moving onto rust.
I can build and run our rust test application as described here on the updated module, so that;'s good!, but it's about the only thing I can run... (the pytest does also pass).
Trying the application from here (after fixing compiler issues, here it is for convenience)
use wasi::http::types::{
Fields, IncomingRequest, OutgoingBody, OutgoingResponse, ResponseOutparam,
};
wasi::http::proxy::export!(Component);
use wasi::cli::environment::get_environment;
struct Component;
const HTML_BODY: &str = r#"<html>
<head>
<title>Hello from WebAssembly!</title>
</head>
<body>
{{ENV_VARS}}
</body>
</html>"#;
impl wasi::exports::http::incoming_handler::Guest for Component {
fn handle(_request: IncomingRequest, response_out: ResponseOutparam) {
let hdrs = Fields::new();
let variables = format!("{:?}", get_environment());
let mesg = String::from(HTML_BODY).replace("{{ENV_VARS}}", &variables);
let _try = hdrs.set(
&"Content-Type".to_string(),
&[b"text/html; charset=utf-8".to_vec()],
);
let _try = hdrs.set(
&"Content-Length".to_string(),
&[mesg.len().to_string().as_bytes().to_vec()],
);
let resp = OutgoingResponse::new(hdrs);
resp.set_status_code(200).unwrap();
let body = resp.body().unwrap();
ResponseOutparam::set(response_out, Ok(resp));
let out = body.write().unwrap();
out.blocking_write_and_flush(mesg.as_bytes()).unwrap();
drop(out);
OutgoingBody::finish(body, None).unwrap();
}
}
Results in (when trying to load the component)
2024/08/29 00:37:16 [alert] 180726#180726 failed to create initial state
Caused by:
0: failed to pre-instantiate the provided component
1: component imports instance `wasi:cli/environment@0.2.1`, but a matching implementation was not found in the linker
2: instance export `get-environment` has the wrong type
3: function implementation is missing
I wonder if that has anything to do with changes like
- wasmtime_wasi::preview2::command::add_to_linker(&mut linker)?;
- wasmtime_wasi_http::proxy::add_only_http_to_linker(&mut linker)?;
+ add_to_linker_async(&mut linker)
+ .context("failed to add to linker")?;
+ //add_only_http_to_linker_sync(&mut linker)
+ // .context("failed to add http to linker")?;
and perhaps
- component,
+ component: proxy,
That prevent reactor (as opposed to proxy) component types from working?
- wasmtime_wasi::preview2::command::add_to_linker(&mut linker)?;
That line in particular was added by
commit 60eb6c43a71fb0f6cf21759917e0247bdb88b892
Author: Andrew Clayton <a.clayton@nginx.com>
Date: Tue Feb 13 16:21:49 2024 +0000
Wasm-wc: Allow to use the 'reactor' adaptor again
With the initial port to wasmtime 17 we could no longer use the
'reactor' adaptor but had to switch to the more restrictive 'proxy'
adaptor.
This meant amongst other things (probably) we could no longer access the
filesystem.
Thanks to Joel Dice for pointing out the fix.
With this we can go back to using the 'reactor' adaptor again and things
are back to working as before.
It's worth noting that you can use either the 'proxy' or 'reactor'
adaptor depending on your requirements.
Cc: Joel Dice <joel.dice@fermyon.com>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
diff --git ./src/wasm-wasi-component/src/lib.rs ./src/wasm-wasi-component/src/lib.rs
index 888074ab..3ee40c4f 100644
--- ./src/wasm-wasi-component/src/lib.rs
+++ ./src/wasm-wasi-component/src/lib.rs
@@ -200,7 +200,8 @@ impl GlobalState {
let component = Component::from_file(&engine, &global_config.component)
.context("failed to compile component")?;
let mut linker = Linker::<StoreState>::new(&engine);
- wasmtime_wasi_http::proxy::add_to_linker(&mut linker)?;
+ wasmtime_wasi::preview2::command::add_to_linker(&mut linker)?;
+ wasmtime_wasi_http::proxy::add_only_http_to_linker(&mut linker)?;
let component = linker
.instantiate_pre(&component)
.context("failed to pre-instantiate the provided component")?;
Will want to verify (and add automated tests?) for filesystem access, if we're not already testing.
Hmm, so, the two add_to_linker's do allow the component to load and run, thanks!
However when then trying to get the environment variables (with cx.inherit_env();) things go awry...
The component loads, but then crashes when making a request...
$ curl localhost:8080/
curl: (18) transfer closed with 5014 bytes remaining to read
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0xe93f - wit-component:shim!indirect-wasi:io/streams@0.2.1-[method]output-stream.blocking-write-and-flush
1: 0x3471 - <unknown>!<wasm function 43>
1: Buffer too large for blocking-write-and-flush (expected at most 4096)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2024/08/30 14:22:30 [alert] 431991#431991 app process 431992 exited on signal 6 (core dumped)
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0xe93f - wit-component:shim!indirect-wasi:io/streams@0.2.1-[method]output-stream.blocking-write-and-flush
1: 0x3471 - <unknown>!<wasm function 43>
1: Buffer too large for blocking-write-and-flush (expected at most 4096)
Stack backtrace:
0: anyhow::error::<impl anyhow::Error>::msg
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::result::unwrap_failed
3: wasm_wasi_component::GlobalState::run::{{closure}}::{{closure}}
4: std::panicking::try
In the meantime I'll try and see if filesystem access is working...
@ac000 do you have the code for your C based wasi component handy so I can reproduce the issue you're seeing?
That's a strange crash. I am able to get the example module from above to work and print out envvars in its response, so I'm not sure where / how it's failing on your end.
I can't get filesystem access to work, neither in Unit nor with wasmtime serve --dir PATH
. So something's weird there and needs deeper investigation.
@javorszky
There is https://git.digital-domain.net/project_blackbird.git/tree/c/wasi-http/0.2.0/echo-request for example. But it's giving me the same issue as the rust application in my initial comment.
Well, not exactly the same error...
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0xe8f7 - wit-component:shim!indirect-wasi:http/types@0.2.0-[static]response-outparam.set
1: 0x473d - module.wasm!wasi_http_types_static_response_outparam_set
2: 0x59f6 - module.wasm!exports_wasi_http_incoming_handler_handle
3: 0x4c87 - module.wasm!__wasm_export_exports_wasi_http_incoming_handler_handle
1: unknown handle index 0
Stack backtrace:
0: anyhow::error::<impl anyhow::Error>::msg
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::result::unwrap_failed
3: wasm_wasi_component::GlobalState::run::{{closure}}::{{closure}}
4: std::panicking::try
That's a strange crash. I am able to get the example module from above to work and print out envvars in its response, so I'm not sure where / how it's failing on your end.
I can't get filesystem access to work, neither in Unit nor with
wasmtime serve --dir PATH
. So something's weird there and needs deeper investigation.
Seeing the same thing
thread '<unnamed>' panicked at src/lib.rs:27:51:
Unable to write file: Custom { kind: Uncategorized, error: "failed to find a pre-opened file descriptor through which \"/tmp/wasm-wc-fs-test\" could be opened" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0x8085 - et.wasm!__rust_start_panic
1: 0x7e50 - et.wasm!rust_panic
2: 0x7c06 - et.wasm!_ZN3std9panicking20rust_panic_with_hook17haaccccfe5a373acdE
3: 0x70ad - et.wasm!_ZN3std9panicking19begin_panic_handler28_$u7b$$u7b$closure$u7d$$u7d$17hea3feb189860033dE
4: 0x7014 - et.wasm!_ZN3std10sys_common9backtrace26__rust_end_short_backtrace17hd9f533f0d74942c6E
5: 0x779e - et.wasm!rust_begin_unwind
6: 0xac53 - et.wasm!_ZN4core9panicking9panic_fmt17hcba33b52fb7a6f32E
7: 0xc881 - et.wasm!_ZN4core6result13unwrap_failed17he1e30e4458e0844aE
8: 0x2272 - et.wasm!_ZN91_$LT$et..Component$u20$as$u20$wasi..proxy..exports..wasi..http..incoming_handler..Guest$GT$6handle17h1e747c577217c4a8E
9: 0x2315 - et.wasm!wasi:http/incoming-handler@0.2.1#handle
1: wasm trap: wasm `unreachable` instruction executed
Stack backtrace:
0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
stack backtrace:
0: rust_begin_unwind
1: core::panicking::panic_fmt
2: core::result::unwrap_failed
3: wasm_wasi_component::GlobalState::run::{{closure}}::{{closure}}
4: std::panicking::try
I wonder if it's due to the removal of
for dir in self.global_config.dirs.iter() {
- let fd = Dir::open_ambient_dir(dir, ambient_authority())
- .with_context(|| {
- format!("failed to open directory '{dir}'")
- })?;
The other slightly strange thing is that the preopened_dir function now seems to only take three arguments whereas we're passing in four...
As an aside, with most things wasm/rust seemingly broken for me, I double checked that the wasm language module and unit-wasm examples still work with libwasmtime v24, including filesystem access, so that's something!
Having setup a clean rust/cargo environment (using rustup rather than distro packages) I can now load and run the above rust component and get the environment variables.
But filesystem access is still not working. The language module does open the directory at request time
[pid 17597] openat(AT_FDCWD, "/var/tmp", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = 17
but I guess it doesn't set the ambient authority on it like it used to...
The other slightly strange thing is that the preopened_dir function now seems to only take three arguments whereas we're passing in four...
I think we're using the method on the WasiCtxBuilder, which does take 2 dirs: https://docs.rs/wasmtime-wasi/latest/wasmtime_wasi/struct.WasiCtxBuilder.html#method.preopened_dir
One thing I notice is that with a component that works under wasmtime 17, we have these filesystems imports
import wasi:filesystem/types@0.2.0;
import wasi:filesystem/preopens@0.2.0;
Which seem to be missing in the latest component built with cargo-component v0.15.0
Building the Rust code from https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md as a command component (i.e. src/main.rs with a main() function) does include them. That then runs under wasmtime run and works...
Tried about a bazilliion different things, getting nowhere fast. Even tried taking cargo-component out the equation by using a mixture of cargo-build and wasm-tools but still crashes
thread '<unnamed>' panicked at src/lib.rs:27:51:
Unable to write file: Custom { kind: Uncategorized, error: "failed to find a pre-opened file descriptor through which \"/tmp/wasm-wc-fs-test\" could be opened" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0x207fa - et.wasm!__rust_start_panic
1: 0x205c5 - et.wasm!rust_panic
2: 0x2037b - et.wasm!_ZN3std9panicking20rust_panic_with_hook17h8bb4f94cf9e68e20E
3: 0x1f79d - et.wasm!_ZN3std9panicking19begin_panic_handler28_$u7b$$u7b$closure$u7d$$u7d$17h2c354a3372fcca00E
4: 0x1f704 - et.wasm!_ZN3std10sys_common9backtrace26__rust_end_short_backtrace17hf791a0fba63af5e9E
5: 0x1ff13 - et.wasm!rust_begin_unwind
6: 0x25513 - et.wasm!_ZN4core9panicking9panic_fmt17haadcabb094f4c85bE
7: 0x27186 - et.wasm!_ZN4core6result13unwrap_failed17hd09ff05c9c2fb25fE
8: 0x357b - et.wasm!_ZN4core6result19Result$LT$T$C$E$GT$6expect17h128bef27c8ee3bccE
9: 0x1f07 - et.wasm!_ZN91_$LT$et..Component$u20$as$u20$wasi..proxy..exports..wasi..http..incoming_handler..Guest$GT$6handle17h08a6114a11b81d6cE
10: 0x7ff8 - et.wasm!_ZN4wasi5proxy7exports4wasi4http16incoming_handler19_export_handle_cabi17hdc42bed91e5ceefbE
11: 0x2919 - et.wasm!wasi:http/incoming-handler@0.2.1#handle
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
1: wasm trap: wasm `unreachable` instruction executed
Gotta love the symbol mangling, looks like something Rust picked up from C++
Opened issue on the wasmtime repository: https://github.com/bytecodealliance/wasmtime/issues/9194
OK, so removing proxy = true
from Cargo.toml
does make it work on my Fedora VM (with rust/cargo from rustup).
Things are still totally b0rked on my Fedora workstation using distribution packages of rust/cargo.
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0x108ac - wit-component:shim!indirect-wasi:io/streams@0.2.1-[method]output-stream.blocking-write-and-flush
1: 0x3aa4 - <unknown>!<wasm function 43>
1: Buffer too large for blocking-write-and-flush (expected at most 4096)
That is not even trying any filesystem stuff...
If we're going ahead with this, then those commits should be squashed and have a commit subject prefix of wasm-wc
...
I'd suggest something like
wasm-wc: Update the wasmtime-crate to v24.0.0
OK, quick thing...
Could you run from the repository root on your ava-wasmtime branch
$ rustfmt --edition 2021 src/wasm-wasi-component/src/lib.rs
$ git add src/wasm-wasi-component/src/lib.rs
$ git commit --amend --no-edit
$ git push -f ... ...
NOTE: NOT A BUG
I had
fs::write("/var/tmp/wasm-wc-fs-test", "test").expect("Unable to write file");
not realising .expect() would cause a panic if the call failed!
Simply changing it to
let _ = fs::write("/var/tmp/wasm-wc-fs-test", "test");
gets rid of the crash...
I wasn't seeing the crash with the previous version of the module as a I was using C for the components (really need to get this working again with this version of the module) and was not manually triggering a crash if the open(2) failed...
================================================================================================= Just for the record. This does have the known issue in that if you try to access a directory that isn't pre-opened, the language module will crash (this doesn't happen with the current module)
2024/09/04 21:30:49 [info] 4111#4111 "my-wasm-component" application started
thread '<unnamed>' panicked at src/lib.rs:28:55:
Unable to write file: Custom { kind: Uncategorized, error: "failed to find a pre-opened file descriptor through which \"/var/tmp/wasm-wc-fs-test\" could be opened" }
stack backtrace:
thread 'tokio-runtime-worker' panicked at src/lib.rs:248:45:
failed to handle request: failed to invoke wasm `handle`
Caused by:
0: error while executing at wasm backtrace:
0: 0x207fa - et.wasm!__rust_start_panic
1: 0x205c5 - et.wasm!rust_panic
2: 0x2037b - et.wasm!_ZN3std9panicking20rust_panic_with_hook17h8bb4f94cf9e68e20E
3: 0x1f79d - et.wasm!_ZN3std9panicking19begin_panic_handler28_$u7b$$u7b$closure$u7d$$u7d$17h2c354a3372fcca00E
4: 0x1f704 - et.wasm!_ZN3std10sys_common9backtrace26__rust_end_short_backtrace17hf791a0fba63af5e9E
5: 0x1ff13 - et.wasm!rust_begin_unwind
6: 0x25513 - et.wasm!_ZN4core9panicking9panic_fmt17haadcabb094f4c85bE
7: 0x27186 - et.wasm!_ZN4core6result13unwrap_failed17hd09ff05c9c2fb25fE
8: 0x357b - et.wasm!_ZN4core6result19Result$LT$T$C$E$GT$6expect17h128bef27c8ee3bccE
9: 0x1f07 - et.wasm!_ZN91_$LT$et..Component$u20$as$u20$wasi..proxy..exports..wasi..http..incoming_handler..Guest$GT$6handle17h08a6114a11b81d6cE
10: 0x7ff8 - et.wasm!_ZN4wasi5proxy7exports4wasi4http16incoming_handler19_export_handle_cabi17hdc42bed91e5ceefbE
11: 0x2919 - et.wasm!wasi:http/incoming-handler@0.2.1#handle
1: wasm trap: wasm `unreachable` instruction executed
Stack backtrace:
0: anyhow::error::<impl core::convert::From<E> for anyhow::Error>::from
stack backtrace:
0: 0x7fdf149ee4f5 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hd736fd5964392270
1: 0x7fdf14a13f1b - core::fmt::write::hc6043626647b98ea
2: 0x7fdf149eb05f - std::io::Write::write_fmt::h0d24b3e0473045db
3: 0x7fdf149ee2ce - std::sys_common::backtrace::print::h45eb8174d25a1e76
4: 0x7fdf149ef4a9 - std::panicking::default_hook::{{closure}}::haf3f0170eb4f3b53
5: 0x7fdf149ef24a - std::panicking::default_hook::hb5d3b27aa9f6dcda
6: 0x7fdf149ef943 - std::panicking::rust_panic_with_hook::h6b49d59f86ee588c
7: 0x7fdf149ef824 - std::panicking::begin_panic_handler::{{closure}}::hd4c2f7ed79b82b70
8: 0x7fdf149ee9b9 - std::sys_common::backtrace::__rust_end_short_backtrace::h2946d6d32d7ea1ad
9: 0x7fdf149ef557 - rust_begin_unwind
10: 0x7fdf14301c43 - core::panicking::panic_fmt::ha02418e5cd774672
11: 0x7fdf14302136 - core::result::unwrap_failed::h55f86ada3ace5ed2
12: 0x7fdf14406623 - wasm_wasi_component::GlobalState::run::{{closure}}::{{closure}}::hde6d9ddccf4e74b6
13: 0x7fdf1440e978 - std::panicking::try::hedbe02d01cfa8c6e
2024/09/04 21:30:52 [alert] 4110#4110 app process 4111 exited on signal 6 (core dumped)
This PR bumps the libwasmtime version used in both the wasm and wasm-wasi-component modules to version 24.
This PR adds additions to the tooling to properly build libwasmtime for the wasm module. This introduces the need for cmake on the host. Dockerfiles are not updated to reflect this as part of this PR.
Fixes: https://github.com/nginx/unit/issues/1392