Stream: git-wasmtime

Topic: wasmtime / issue #13920 C API wasip2 stdout/stderr not wo...


view this post on Zulip Wasmtime GitHub notifications bot (Jul 21 2026 at 14:09):

amytimed opened issue #13920:

Test Case

Any wasip2 WASM that prints to console. I used one that does nothing except print hello world.

Expected vs actual

stdout/stderr should be inherited, but nothing is printed to the console. The same WASM file ran from the wasmtime CLI prints correctly.

Reproducing

I'm using the C API from Rust. (I understand that wasmtime is a rust crate which I could also use directly, but I wanted to avoid bringing in wasmtime's dependency tree directly when compiling my project)

Here's the code I'm using to run the wasm:

use wasmtime::*; // This is not the rust crate, this is bindings from rust-bindgen to the C API
use std::ptr;

fn main() {
    unsafe {
        let conf = wasm_config_new();
        assert!(!conf.is_null());
        wasmtime_config_wasm_component_model_set(conf, true);
        let engine = wasm_engine_new_with_config(conf);
        assert!(!engine.is_null());

        let store = wasmtime_store_new(engine, ptr::null_mut(), None);
        assert!(!store.is_null());

        let context = wasmtime_store_context(store);
        assert!(!context.is_null());


        let wasi_config = wasi_config_new();
        assert!(!wasi_config.is_null());
        wasi_config_inherit_stdout(wasi_config);
        wasi_config_inherit_stderr(wasi_config);

        let err = wasmtime_context_set_wasi(context, wasi_config);
        if !err.is_null() {
            panic!("Failed to set up WASI");
        }

        let wasm = std::fs::read("/home/Amy/Documents/simulo/hey_guys.wasm").unwrap();

        let mut component = std::mem::zeroed();
        let err = wasmtime_component_new(engine, wasm.as_ptr(), wasm.len(), &mut component);
        if !err.is_null() {
            let mut bytes = std::mem::zeroed();
            wasm_byte_vec_new_uninitialized(&mut bytes, 256);
            wasmtime_error_message(err, &mut bytes);
            let c_str = std::ffi::CString::from_raw(*&bytes.data);
            panic!("Failed to create component: {}", c_str.to_str().unwrap());
            // wasm_byte_vec_delete(bytes);
        }
        assert!(!component.is_null());

        let linker = wasmtime_component_linker_new(engine);
        let err = wasmtime_component_linker_add_wasip2(linker);
        if !err.is_null() {
            panic!("Failed to add WASI to linker");
        }

        let mut instance = std::mem::zeroed();
        let err = wasmtime_component_linker_instantiate(linker, context, component, &mut instance);
        if !err.is_null() {
            panic!("Failed to instantiate component");
        }

        let c_str = std::ffi::CString::new("wasi:cli/run@0.2.0").unwrap();
        let c_world: *const std::ffi::c_char = c_str.as_ptr() as *const std::ffi::c_char;
        let index1 = wasmtime_component_instance_get_export_index(&instance, context, ptr::null(), c_world, c_str.count_bytes());
        if index1.is_null() {
            panic!("Failed to get WASI CLI");
        }

        let c_str = std::ffi::CString::new("run").unwrap();
        let c_world: *const std::ffi::c_char = c_str.as_ptr() as *const std::ffi::c_char;
        let index2 = wasmtime_component_instance_get_export_index(&instance, context, index1, c_world, c_str.count_bytes());
        if index2.is_null() {
            panic!("Failed to get run function");
        }

        let mut func = std::mem::zeroed();
        if !wasmtime_component_instance_get_func(&instance, context, index2, &mut func) {
            panic!("Failed to get run function");
        }

        wasmtime_component_export_index_delete(index1);
        wasmtime_component_export_index_delete(index2);

        let args: [wasmtime_component_val_t; 0] = [];
        let mut results: [wasmtime_component_val_t; 0] = [];
        wasmtime_component_func_call(&mut func, context, args.as_ptr(), 0, results.as_mut_ptr(),0);

        std::thread::sleep_ms(1000); // sleep in case it just didn't flush in time

        wasmtime_component_linker_delete(linker);
        wasmtime_component_delete(component);
        wasmtime_store_delete(store);
        wasm_engine_delete(engine);

    }
}

Versions and Environment

Wasmtime version: 46.0.1

Operating system: Linux Mint, x86_64

view this post on Zulip Wasmtime GitHub notifications bot (Jul 21 2026 at 14:09):

amytimed added the bug label to Issue #13920.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 21 2026 at 14:15):

amytimed closed issue #13920:

Test Case

Any wasip2 WASM that prints to console. I used one that does nothing except print hello world.

Expected vs actual

stdout/stderr should be inherited, but nothing is printed to the console. The same WASM file ran from the wasmtime CLI prints correctly.

Reproducing

I'm using the C API from Rust. (I understand that wasmtime is a rust crate which I could also use directly, but I wanted to avoid bringing in wasmtime's dependency tree directly when compiling my project)

Here's the code I'm using to run the wasm:

use wasmtime::*; // This is not the rust crate, this is bindings from rust-bindgen to the C API
use std::ptr;

fn main() {
    unsafe {
        let conf = wasm_config_new();
        assert!(!conf.is_null());
        wasmtime_config_wasm_component_model_set(conf, true);
        let engine = wasm_engine_new_with_config(conf);
        assert!(!engine.is_null());

        let store = wasmtime_store_new(engine, ptr::null_mut(), None);
        assert!(!store.is_null());

        let context = wasmtime_store_context(store);
        assert!(!context.is_null());


        let wasi_config = wasi_config_new();
        assert!(!wasi_config.is_null());
        wasi_config_inherit_stdout(wasi_config);
        wasi_config_inherit_stderr(wasi_config);

        let err = wasmtime_context_set_wasi(context, wasi_config);
        if !err.is_null() {
            panic!("Failed to set up WASI");
        }

        let wasm = std::fs::read("/home/Amy/Documents/simulo/hey_guys.wasm").unwrap();

        let mut component = std::mem::zeroed();
        let err = wasmtime_component_new(engine, wasm.as_ptr(), wasm.len(), &mut component);
        if !err.is_null() {
            let mut bytes = std::mem::zeroed();
            wasm_byte_vec_new_uninitialized(&mut bytes, 256);
            wasmtime_error_message(err, &mut bytes);
            let c_str = std::ffi::CString::from_raw(*&bytes.data);
            panic!("Failed to create component: {}", c_str.to_str().unwrap());
            // wasm_byte_vec_delete(bytes);
        }
        assert!(!component.is_null());

        let linker = wasmtime_component_linker_new(engine);
        let err = wasmtime_component_linker_add_wasip2(linker);
        if !err.is_null() {
            panic!("Failed to add WASI to linker");
        }

        let mut instance = std::mem::zeroed();
        let err = wasmtime_component_linker_instantiate(linker, context, component, &mut instance);
        if !err.is_null() {
            panic!("Failed to instantiate component");
        }

        let c_str = std::ffi::CString::new("wasi:cli/run@0.2.0").unwrap();
        let c_world: *const std::ffi::c_char = c_str.as_ptr() as *const std::ffi::c_char;
        let index1 = wasmtime_component_instance_get_export_index(&instance, context, ptr::null(), c_world, c_str.count_bytes());
        if index1.is_null() {
            panic!("Failed to get WASI CLI");
        }

        let c_str = std::ffi::CString::new("run").unwrap();
        let c_world: *const std::ffi::c_char = c_str.as_ptr() as *const std::ffi::c_char;
        let index2 = wasmtime_component_instance_get_export_index(&instance, context, index1, c_world, c_str.count_bytes());
        if index2.is_null() {
            panic!("Failed to get run function");
        }

        let mut func = std::mem::zeroed();
        if !wasmtime_component_instance_get_func(&instance, context, index2, &mut func) {
            panic!("Failed to get run function");
        }

        wasmtime_component_export_index_delete(index1);
        wasmtime_component_export_index_delete(index2);

        let args: [wasmtime_component_val_t; 0] = [];
        let mut results: [wasmtime_component_val_t; 0] = [];
        wasmtime_component_func_call(&mut func, context, args.as_ptr(), 0, results.as_mut_ptr(),0);

        std::thread::sleep_ms(1000); // sleep in case it just didn't flush in time

        wasmtime_component_linker_delete(linker);
        wasmtime_component_delete(component);
        wasmtime_store_delete(store);
        wasm_engine_delete(engine);

    }
}

Versions and Environment

Wasmtime version: 46.0.1

Operating system: Linux Mint, x86_64

view this post on Zulip Wasmtime GitHub notifications bot (Jul 21 2026 at 14:15):

amytimed commented on issue #13920:

Nevermind, I forgot to check if the func call errored


Last updated: Jul 29 2026 at 05:03 UTC