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

feat(wamr): add wasm-mico-runtime shim implementation #508

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Mossaka
Copy link
Member

@Mossaka Mossaka commented Mar 7, 2024

this commit adds an additional shim implementation: Wamr using wamr-rust-sdk. At the moment, the shim isn't working with an error "thread signal env initialized failed" which I am not sure exactly sure what it means. Will ask the Wamr team for clarification. There are also some pain points using the newly created wamr-rust-sdk which I wrote as TODOs in the comment.

This PR should close #337

FYI @squillace @0xE282B0 @lum1n0us

this commit adds an additional shim implementation: Wamr using
wamr-rust-sdk

Signed-off-by: jiaxiao zhou <[email protected]>
@@ -3,7 +3,7 @@ INSTALL ?= install
CARGO ?= cargo
LN ?= ln -sf
TEST_IMG_NAME ?= wasmtest:latest
RUNTIMES ?= wasmedge wasmtime wasmer
RUNTIMES ?= wasmedge wasmtime wasmer wamr
Copy link
Member Author

Choose a reason for hiding this comment

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

Need to add wamr to CI

@squillace
Copy link

this is GREAT!

Signed-off-by: jiaxiao zhou <[email protected]>
let instance = WamrInstnace::new(&module, 1024 * 64)
.map_err(|e| anyhow::Error::msg(format!("Failed to create instance: {:?}", e)))?;

// TODO: bug: failed at line above saying: `thread signal env initialized failed`
Copy link

Choose a reason for hiding this comment

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

I am thinking about Self { runtime } may has been destroyed. It happened several times in my test cases when implementing rust-sdk. Is there a quick way we can confirm that?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah i believe that when the variable let runtime = Runtime::new() goes out of scope, the Drop() will be invoked to destruct it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's probably why I favor the design of a binding the runtime to the variable and pass that to instances like wasmtime does.

    let engine = Engine::default();
    let module = Module::new(&engine, wat)?;
    let mut store = Store::new(&engine, 4);

Choose a reason for hiding this comment

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

@macko99
Copy link

macko99 commented Jul 9, 2024

@Mossaka does wamr work already?

@lum1n0us
Copy link

WAMR team can provide help as much as possible.

@Mossaka
Copy link
Member Author

Mossaka commented Jul 10, 2024

Hey @macko99, thanks for reaching out! It doesn't work at the moment and this PR needs some love. I am going to refresh it and see if the errors will be resolved by the Wamr SDK. If not, I appreciate the Wamr team to offer some help. FYI @lum1n0us

@macko99
Copy link

macko99 commented Jul 11, 2024

@Mossaka it would be great if you could check the status of this PR! Keep me posted

@macko99
Copy link

macko99 commented Jul 13, 2024

@Mossaka I have made a small update to this PR link. The issues are still there. I played around with WAMR, warm-rust-sdk and runwasi without any luck. I'm afraid my understanding of the wamr runtime is holding me back at this point...

@lum1n0us
Copy link

Based on the description in bytecodealliance/wasm-micro-runtime#3627.

It requires to config pre-opens of WASI arguments. Here is a reference:

https://github.com/bytecodealliance/wamr-rust-sdk/blob/main/examples/wasi-hello/src/main.rs#L19-#L21

@macko99
Copy link

macko99 commented Jul 14, 2024

@lum1n0us please take a look at the PR

I do set
let wasi_ctx = WasiCtxBuilder::new() .set_pre_open_path(vec!["/"], vec!["/"]) .set_env_vars(envs.iter().map(String::as_str).collect()) .build();

I have also tried with other dirs, just like in an example, it fails with "Error: ExecutionError("Exception: unreachable")"

To clarify:
-when setting envs by set_env_vars the shim exists with no error or "thread signal env initialized failed"
-when setting set_pre_open_path to "/:/" I get "error running start function: Failed to create instance: InstantiationFailure("error while pre-opening mapped directory: invalid map"
-when setting set_pre_open_path to ".:" I get "Error: ExecutionError("Exception: unreachable")"

@lum1n0us
Copy link

@macko99 I am thinking about running the PR locally. Is there any guides about how to?

@lum1n0us
Copy link

Like, may I ask, if using sudo ctr run --rm --runtime=io.containerd.[ wasmedge | wasmtime | wasmer ].v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm /wasi-demo-app.wasm echo 'hello' to test, how to check the log, especially error info?

@Mossaka
Copy link
Member Author

Mossaka commented Jul 16, 2024

Like, may I ask, if using sudo ctr run --rm --runtime=io.containerd.[ wasmedge | wasmtime | wasmer ].v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm /wasi-demo-app.wasm echo 'hello' to test, how to check the log, especially error info?

The log is containerd's log and containerd is running on your local host as a deamon process. You can try journalctl -u containerd to get containerd logs.

You may also refer to this doc on how to adjust logging levels. Note that you may need to restart containerd after modiying its config files by doing systemctl restart containerd

@lum1n0us
Copy link

Thanks. Please don't mind my lack of related knowledge.

  • Is there a way to check println!() messages from runwasi, wamr-rust-sdk and even WAMR library.
  • Is there a way that I can use rust-lldb to debug WAMR library behavior.
  • Is there a way that I can simplify the demo, I mean to shrink sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm /wasi-demo-app.wasm echo "hello" into few lines?

@Mossaka
Copy link
Member Author

Mossaka commented Jul 19, 2024

Is there a way to check println!() messages from runwasi, wamr-rust-sdk and even WAMR library.

If you wanna see logs from runwasi and sdk code, you can put log::info!() and see the messages in Containerd logs.

Is there a way that I can use rust-lldb to debug WAMR library behavior.

I've not tried this but I did try attaching the PID to vscode debugger to debug the shim binary.

Is there a way that I can simplify the demo, I mean to shrink sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm /wasi-demo-app.wasm echo "hello" into few lines?

What do you mean by this exactly? If you wanna create a simply wasm image, you can do so by authoring a hello world program, compile it to wasm, and package it as a OCI image, and then run it with ctr. You can take a look at crates/wasi-demo-app for how we packaged the wasi-demo application as a container.

@lum1n0us
Copy link

Try this command but failed:

$ sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm echo "hi"
ctr: failed to create shim task: Others("exec process failed with error error in executing process : wasmtime executor can't handle spec"): unknown

Using journalctl found.

fail_to_start_wasmtime.log

Jul 23 14:01:28 code-factory-4 containerd[35743]: time="2024-07-23T06:01:28.990386595Z" level=error msg="failed to initialize container process: wasmtime executor can't handle spec"
Jul 23 14:01:28 code-factory-4 containerd[35743]: time="2024-07-23T06:01:28.990472575Z" level=error msg="failed to wait for init ready: exec process failed with error error in executing process : wasmtime executor can't handle spec"
Jul 23 14:01:28 code-factory-4 containerd[35743]: time="2024-07-23T06:01:28.990503254Z" level=error msg="failed to run container process err=Channel(ExecError("error in executing process : wasmtime executor can't handle spec"))"

It is similar with #637. Any suggestion?

anyhow::Error::msg(format!("Failed to create module from bytes: {:?}", e))
})?;

module.set_wasi_arg_pre_open_path(vec![String::from("/")], vec![String::from("/")]);

Choose a reason for hiding this comment

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

Suggested change
module.set_wasi_arg_pre_open_path(vec![String::from("/")], vec![String::from("/")]);
module.set_wasi_arg_pre_open_path(vec![String::from("/")], vec![]);

Choose a reason for hiding this comment

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

Still have problems when function.call(). need further investigation. But blocked by above setup issues. I was hoping to check

  • if module is unloaded or released?
  • if there anything unexpected unloaded or released?

@Mossaka
Copy link
Member Author

Mossaka commented Jul 23, 2024

Try this command but failed:

$ sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm echo "hi"
ctr: failed to create shim task: Others("exec process failed with error error in executing process : wasmtime executor can't handle spec"): unknown

Try sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-app:latest testwasm /wasi-demo-app.wasm echo 'hi'?

I believe the wasi-demo-app takes the first argument as the wasm file and the second argument as the command.

@lum1n0us
Copy link

lum1n0us commented Jul 25, 2024

There is an exception in wasi-demo-app.wasm when driving by WAMR. It is triggered by println!. And I guess it is related to crates/containerd-shim-wasm/src/sandbox/stdio.rs and stdio.redirect(). (Because I am enable to use WAMR to execute the same .wasm successfully). Therefore, I am going to ask that in order to support sandbox stdio, is there any requirement for a wasm runtime?

After some investigation, I learned why println! and eprintln! failed. In this specific execution environment:

  • isatty() for STDOUT and STDERR are not a tty.
  • fcntl() for STDOUT and STDERR are O_RDONLY. (this is the root cause. It is supposed to be R_WRONLY)

Therefore, fd_write() to STDOUT and STDERR (triggered by println!() and eprintln!()) will be rejected and raised an exception.


#00: 0x12ea7 - __rust_start_panic
#01: 0x12c30 - rust_panic
#02: 0x12954 - std::panicking::rust_panic_with_hook
#03: 0x11d0d - std::panicking::begin_panic_handler::{{closure}}
#04: 0x11c74 - std::sys_common::backtrace::__rust_end_short_backtrace
#05: 0x1245c - rust_begin_unwind
#06: 0x18140 - core::panicking::panic_fmt
#07: 0x1112f - std::io::stdio::_print
#08: 0x9cad - wasi_demo_app::main    ;; <-- `"echo" => println!("{}", &args[2..].join(" ")),`
#09: 0x2528 - core::ops::function::FnOnce::call_once
#10: 0x9276 - std::sys_common::backtrace::__rust_begin_short_backtrace
#11: 0xcdab - std::rt::lang_start::{{closure}}
#12: 0xf468 - std::rt::lang_start_internal
#13: 0xcd47 - std::rt::lang_start
#14: 0xa54c - __main_void
#15: 0x05bc - _start

@lum1n0us
Copy link

@Mossaka need your help to take a look at below two problems. Both return values in runwasi/containerd are different with other execution environments.

isatty() for STDOUT and STDERR are not a tty.
fcntl() for STDOUT and STDERR are O_RDONLY. (this is the root cause. It is supposed to be R_WRONLY)

@lum1n0us
Copy link

the shim isn't working with an error "thread signal env initialized failed" which I am not sure exactly sure what it means.

A workaround of this issue is to disable memory bounds check with .define("WAMR_DISABLE_HW_BOUND_CHECK", "1"). Just like #508. And latest wamr-rust-sdk has synced it(https://github.com/bytecodealliance/wamr-rust-sdk/blob/main/crates/wamr-sys/build.rs)

But the reason of this problem still bothers me. HW_BOUND_CHECK of WAMR will touch guard pages around wasm linear memory(mprotect() and ) and use a signal handler to catch signals if a memory operation accesses a invalid address. @Mossaka Does the sandbox of runwasi allow both operations?

@lum1n0us
Copy link

@Mossaka. Above unanticipated behaviors of sandbox(read-only stdout and guard page failures) still exist. Hope somebody would take a look. We made some workarounds in WAMR and wamr-rust-sdk. #642 should work if following #642 (comment).

@devigned
Copy link
Contributor

@lum1n0us, @Mossaka is on holiday. I'll give this some attention later today / tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add webassembly-micro-runtime support
5 participants