TheQuantumPhysicist added the bug label to Issue #9515.
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
- Create the wasm file
- Run the given code
- 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.
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.
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
- Create the wasm file
- Run the given code
- 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.
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