Stream: wasmtime

Topic: ✔ Execution error in component using preview1 adapter


view this post on Zulip Dan (Jul 12 2023 at 00:12):

Hello all! For a little context, I'm trying to compile and run Ruby 3.2 as a component. I have a core module compiled of the Ruby runtime, which I then encode as a component using the command variant of the preview1 adapter.

Executing the component with Wasmtime throws the following error:

error while executing at wasm backtrace:
    0: 0xf50b06 - wit-component:adapter:wasi_snapshot_preview1!wasi_snapshot_preview1::bindings::wasi::cli_base::exit::exit::hf14a756e1735c0fa
    1: 0xf4ff1e - wit-component:adapter:wasi_snapshot_preview1!proc_exit
    2: 0xf55660 - wit-component:shim!adapt-wasi_snapshot_preview1-proc_exit
    3: 0x4aa733 - <unknown>!<wasm function 5297>
    4: 0x5147 - <unknown>!<wasm function 39>
    5: 0xf46400 - wit-component:adapter:wasi_snapshot_preview1!run

Grepping the Ruby component with wasm-tools print looking for whatever function 39 is, I see these lines:

(func $adapt-wasi_snapshot_preview1-environ_get (;39;) (type 15) (param i32 i32) (result i32)
      i32.const 39
    (export "39" (func $adapt-wasi_snapshot_preview1-environ_get))

which I believe indicates that the crash stems from a call to environ_get -- the Ruby runtime checks the value of env var RUBY_PLATFORM, so it makes sense that the crash is happening early.

I'm using the Rust wasmtime crate, pinned to GitHub rev a330867. The component encoding uses the Rust wasm-tools crate, pinned to GitHub rev 0263c2f. I believe both of these revs are current with recent changes to the preview1 shim. The adapter module itself is compiled from latest wasmtime rev 80e68c3 .

I guess at the moment I'm trying to figure out if this is a bug in the preview1 adapter, or if I've maybe missed something on my end? Please let me know if I can provide more detail!

view this post on Zulip Dan (Jul 12 2023 at 13:43):

the Ruby runtime checks the value of env var RUBY_PLATFORM, so it makes sense that the crash is happening early

sorry I worded this strangely; I meant that the crash seemed to be happening early (before trying to run the script specified in the arguments) and the RUBY_PLATFORM check also happens early, so it tracks to me that the error would originate from environ_get

view this post on Zulip Alex Crichton (Jul 12 2023 at 14:04):

That looks like ruby itself might be calling exit from the stack trace. Is it possible to build ruby with debug info or symbols? Alternatively you can pass -p to print to get offsets to correlate

view this post on Zulip Alex Crichton (Jul 12 2023 at 14:06):

The <unknown> module in the backtrace is likely ruby and everything else looks like adapter or wit component stuff

view this post on Zulip Dan (Jul 12 2023 at 16:20):

@Alex Crichton I've just tried compiling ruby with -O0 -fno-fast-math -ggdb3 however I now get a cranelift panic when loading the module:
thread '<unnamed>' panicked at 'assertion failed: x < (1 << bits)', /home/xlem/.cargo/git/checkouts/wasmtime-41807828cb3a7a7e/a330867/cranelift/codegen/src/ir/dfg.rs:551:9

I will try matching up the offsets with wasm-print -p on the release build shortly and report back!

view this post on Zulip Alex Crichton (Jul 12 2023 at 16:23):

oh dear! If you can share that module that'd be much appreicated to reproduce the cranelift issue

view this post on Zulip Dan (Jul 12 2023 at 16:28):

Sure no problem! The module I'm testing has another WIT component embedded which is specific to my project; would it be easier to debug with a "vanilla" build (i.e. just debug mode ruby encoded with the preview1 adapter)?

view this post on Zulip Alex Crichton (Jul 12 2023 at 16:29):

if you've got some binary blob that panics cranelift that's good enough to send over and we can dig in from there

view this post on Zulip Dan (Jul 12 2023 at 16:41):

ok great; blob attached (compressed as tar.gz). thanks for looking into this!

rubyfn.wasm.tar.gz

view this post on Zulip Alex Crichton (Jul 12 2023 at 16:46):

ok I'll try and minimize the panic, but for the runtime issue there's unfortunately no easy way to reproduce outside of an embedding right now due to no CLI support for components, so if you're able to keep pushing on that it'd be appreciated

view this post on Zulip Dan (Jul 12 2023 at 16:52):

for sure! I'll be working on this some more later this afternoon, I'll let you know where I end up with it

view this post on Zulip Alex Crichton (Jul 12 2023 at 16:54):

First look at this is that there's probably a giant function in rubyfn.wasm which should give a better error, but it's blowing a limit in cranelift which leads to a panic as opposed to a first-class error

view this post on Zulip Alex Crichton (Jul 12 2023 at 16:55):

oof there are some big functions in here, taking upwards of 10s to compile

view this post on Zulip Alex Crichton (Jul 12 2023 at 17:16):

ok looks like this is definitely a case of "that function is too big". If you pass --opt-level 0 to wasmtime compile the panic goes away, but cranelift fails with Error: Compilation error: Code for function is too large when it runs out of virtual registers during register allocation for one of the functions. My guess is that -ggdb3 deoptimized a bit too much and the function is just way too big.

You could try passing -O1 to the C compiler to get at least symbols, or perhaps -gline-tables-only (I forget what that option is actually called, -g1?) to generate less debuginfo which may deoptimize less

view this post on Zulip Dan (Jul 12 2023 at 18:27):

hmm so passing -O1 and -g1 compiles, but doesn't provide any extra info in the stack trace of the crash. I'll keep playing with it

view this post on Zulip Jamey Sharp (Jul 12 2023 at 20:19):

I think I remember there's a common issue of the names section getting stripped out by the toolchain. Maybe it was that clang invokes wasm-opt by default if that's installed?

view this post on Zulip Dan (Jul 13 2023 at 11:30):

A-ha! yes you're right. After passing -O1 -g to wasm-opt I get useful debugging symbols (the Ruby build uses a dummy wasm-opt at first, then calls wasm-opt itself with specified args).

This revealed that it is indeed Ruby itself calling proc_exit. I was thinking it was weird that no errors were logged prior to the exit, and in a case of "changing too many things at once", I realized that this particular code path didn't attach stderr to the module ... enabling that I found that I'd built Ruby without a required built-in gem.

Now it executes fine! Or at least without error. It never seems to run my script, but that is likely another application-level issue on my part so I'll mark this as resolved.

tyvm @Alex Crichton and @Jamey Sharp !!

view this post on Zulip Notification Bot (Jul 13 2023 at 12:10):

Dan has marked this topic as resolved.


Last updated: Oct 23 2024 at 20:03 UTC