Stream: git-wasmtime

Topic: wasmtime / issue #9515 Panic when calling host function i...


view this post on Zulip Wasmtime GitHub notifications bot (Oct 28 2024 at 16:15):

TheQuantumPhysicist added the bug label to Issue #9515.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 28 2024 at 16:15):

TheQuantumPhysicist opened issue #9515:

Test Case

use std::future::Future;
use wasmtime::Config;

#[tokio::main]
async fn main() {
    use wasmtime::{Engine, Linker, Module, Store};
    use wasmtime_wasi::{
        preview1::{self, WasiP1Ctx},
        WasiCtxBuilder,
    };

    let mut config = Config::default();
    config.async_support(true);
    let engine = Engine::new(&config).unwrap();

    let wasm_file_path = get_wasm_filename();

    println!("Opening wasm file: {}", wasm_file_path.display());
    let wasm_bytes = std::fs::read(wasm_file_path).unwrap();

    let module = Module::new(&engine, wasm_bytes).unwrap();

    let mut linker: Linker<WasiP1Ctx> = Linker::new(&engine);

    // // Link, Sync, panics
    // linker
    //     .func_wrap("SomeNamespace", "call_host_function_example", || {
    //         println!("I'm in host!")
    //     })
    //     .unwrap();

    // Link, Async, also panics
    linker
        .func_wrap_async(
            "SomeNamespace",
            "call_host_function_example",
            |mut _caller: wasmtime::Caller<'_, WasiP1Ctx>,
             ()|
             -> Box<dyn Future<Output = ()> + Send> {
                Box::new(async move { println!("I'm in host!") })
            },
        )
        .unwrap();

    // Link wasi functions
    preview1::add_to_linker_sync(&mut linker, |t| t).unwrap();
    let pre = linker.instantiate_pre(&module).unwrap();

    let wasi_ctx = WasiCtxBuilder::new()
        .inherit_stdout()
        .inherit_env()
        .args(&Vec::<&str>::new())
        .build_p1();

    let mut store = Store::new(&engine, wasi_ctx);
    let instance = pre.instantiate_async(&mut store).await.unwrap();

    // This function calls the guest, which in turn calls a function in the host
    let function_call_in_host_from_guest = instance
        .get_typed_func::<(), ()>(&mut store, "call_external_function")
        .unwrap();

    // Call the function in the wasm file that will call the linked function in the host
    function_call_in_host_from_guest
        .call_async(&mut store, ())
        .await
        .unwrap();

    println!("\n\nProgram reached its end successfully. Exiting.\n\n");
}

fn get_wasm_filename() -> std::path::PathBuf {
    let wasm_build_path =
        std::path::PathBuf::from("wasm-test-file/target/wasm32-wasip1/release/wasm-test-file.wasm");
    if wasm_build_path.exists() {
        wasm_build_path
    } else {
        "wasm-test-file.wasm".into()
    }
}

Github wouldn't allow me to upload my wasm file here, it says type isn't supported. So here's the source code that produced it:

fn main() {
    std::panic::set_hook(Box::new(|info| {
        println!("Panic fired: {info}");
        unreachable!()
    }));
}

#[link(wasm_import_module = "SomeNamespace")]
extern "C" {
    fn call_host_function_example();
}

#[no_mangle]
pub fn call_external_function() {
    unsafe {
        println!("Calling host function");
        call_host_function_example();
        println!("Done calling host function");
    }
}

Steps to Reproduce

  1. Create the wasm file
  2. Run the given code
  3. You'll get the panic:
thread 'main' panicked at /Users/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmtime-wasi-26.0.0/src/runtime.rs:108:15:
Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.

Expected Results

The function to be called without panics. Note that this application works fine when async is stripped away.

Actual Results

Panic.

Versions and Environment

Wasmtime version or commit: 0.26.0

Operating system: MacOS

Architecture: Arm (Mac M1)

Extra Info

Anything else you'd like to add?

The program works fine without async. Once async is enabled, it enforces that everything is async (including using call_async instead of call), which then is followed by this issue happening.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 28 2024 at 18:52):

pchickey commented on issue #9515:

The wasm you are executing has nothing to do with this bug, it will appear when any guest calls a wasi import.

Wasmtime-wasi uses tokio under the hood. It implements its synchronous interface, for use in Rust programs that aren't already running tokio, by starting its own tokio runtime privately. Tokio does not permit this when already inside a runtime.

Switch to using preview1::add_to_linker_async and it will not create this private runtime, and instead use the runtime you are already in.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 29 2024 at 06:18):

TheQuantumPhysicist closed issue #9515:

Test Case

use std::future::Future;
use wasmtime::Config;

#[tokio::main]
async fn main() {
    use wasmtime::{Engine, Linker, Module, Store};
    use wasmtime_wasi::{
        preview1::{self, WasiP1Ctx},
        WasiCtxBuilder,
    };

    let mut config = Config::default();
    config.async_support(true);
    let engine = Engine::new(&config).unwrap();

    let wasm_file_path = get_wasm_filename();

    println!("Opening wasm file: {}", wasm_file_path.display());
    let wasm_bytes = std::fs::read(wasm_file_path).unwrap();

    let module = Module::new(&engine, wasm_bytes).unwrap();

    let mut linker: Linker<WasiP1Ctx> = Linker::new(&engine);

    // // Link, Sync, panics
    // linker
    //     .func_wrap("SomeNamespace", "call_host_function_example", || {
    //         println!("I'm in host!")
    //     })
    //     .unwrap();

    // Link, Async, also panics
    linker
        .func_wrap_async(
            "SomeNamespace",
            "call_host_function_example",
            |mut _caller: wasmtime::Caller<'_, WasiP1Ctx>,
             ()|
             -> Box<dyn Future<Output = ()> + Send> {
                Box::new(async move { println!("I'm in host!") })
            },
        )
        .unwrap();

    // Link wasi functions
    preview1::add_to_linker_sync(&mut linker, |t| t).unwrap();
    let pre = linker.instantiate_pre(&module).unwrap();

    let wasi_ctx = WasiCtxBuilder::new()
        .inherit_stdout()
        .inherit_env()
        .args(&Vec::<&str>::new())
        .build_p1();

    let mut store = Store::new(&engine, wasi_ctx);
    let instance = pre.instantiate_async(&mut store).await.unwrap();

    // This function calls the guest, which in turn calls a function in the host
    let function_call_in_host_from_guest = instance
        .get_typed_func::<(), ()>(&mut store, "call_external_function")
        .unwrap();

    // Call the function in the wasm file that will call the linked function in the host
    function_call_in_host_from_guest
        .call_async(&mut store, ())
        .await
        .unwrap();

    println!("\n\nProgram reached its end successfully. Exiting.\n\n");
}

fn get_wasm_filename() -> std::path::PathBuf {
    let wasm_build_path =
        std::path::PathBuf::from("wasm-test-file/target/wasm32-wasip1/release/wasm-test-file.wasm");
    if wasm_build_path.exists() {
        wasm_build_path
    } else {
        "wasm-test-file.wasm".into()
    }
}

Github wouldn't allow me to upload my wasm file here, it says type isn't supported. So here's the source code that produced it:

fn main() {
    std::panic::set_hook(Box::new(|info| {
        println!("Panic fired: {info}");
        unreachable!()
    }));
}

#[link(wasm_import_module = "SomeNamespace")]
extern "C" {
    fn call_host_function_example();
}

#[no_mangle]
pub fn call_external_function() {
    unsafe {
        println!("Calling host function");
        call_host_function_example();
        println!("Done calling host function");
    }
}

Steps to Reproduce

  1. Create the wasm file
  2. Run the given code
  3. You'll get the panic:
thread 'main' panicked at /Users/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmtime-wasi-26.0.0/src/runtime.rs:108:15:
Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.

Expected Results

The function to be called without panics. Note that this application works fine when async is stripped away.

Actual Results

Panic.

Versions and Environment

Wasmtime version or commit: 0.26.0

Operating system: MacOS

Architecture: Arm (Mac M1)

Extra Info

Anything else you'd like to add?

The program works fine without async. Once async is enabled, it enforces that everything is async (including using call_async instead of call), which then is followed by this issue happening.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 29 2024 at 06:18):

TheQuantumPhysicist commented on issue #9515:

You're right. Thank you for explaining. I'm closing this issue.


Last updated: Nov 22 2024 at 16:03 UTC