Stream: git-wasmtime

Topic: wasmtime / issue #12141 `wasmtime_wasi_http` call_handle ...


view this post on Zulip Wasmtime GitHub notifications bot (Dec 08 2025 at 15:49):

if0ne opened issue #12141:

Hi there!

If I try to return an array with a size of 2 MB, everything works fine:

use wasmcloud_component::http;

struct Component;

impl http::Server for Component {
    fn handle(
        _request: http::IncomingRequest,
    ) -> http::Result<http::Response<impl http::OutgoingBody>> {
        let mut bytes = vec![0u8; 2 * 1024 * 1024];
        Ok(http::Response::new(bytes))
    }
}

http::export!(Component);

Output:

curl localhost:8000 --output output.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 2048k    0 2048k    0     0  81.7M      0 --:--:-- --:--:-- --:--:-- 83.3M

But if I make the vector larger than 2 MB:

use wasmcloud_component::http;

struct Component;

impl http::Server for Component {
    fn handle(
        _request: http::IncomingRequest,
    ) -> http::Result<http::Response<impl http::OutgoingBody>> {
        let mut bytes = vec![0u8; 2 * 1024 * 1024 + 1];
        Ok(http::Response::new(bytes))
    }
}

http::export!(Component);

Output:

curl localhost:8000 --output output.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:01:55 --:--:--     0

I debugged the wasmCloud runtime and found that the code freezes on call_handle:

    let (sender, receiver) = tokio::sync::oneshot::channel();
    let scheme = match req.uri().scheme() {
        Some(scheme) if scheme == &hyper::http::uri::Scheme::HTTP => Scheme::Http,
        Some(scheme) if scheme == &hyper::http::uri::Scheme::HTTPS => Scheme::Https,
        Some(scheme) => Scheme::Other(scheme.as_str().to_string()),
        // Fallback to HTTP if no scheme is present
        None => Scheme::Http,
    };
    let req = store.data_mut().new_incoming_request(scheme, req)?;
    let out = store.data_mut().new_response_outparam(sender)?;
    let pre = ProxyPre::new(pre).context("failed to instantiate proxy pre")?;

    // Run the http request itself by instantiating and calling the component
    let proxy = pre.instantiate_async(&mut store).await?;

    proxy
        .wasi_http_incoming_handler()
        .call_handle(&mut store, req, out)
        .await?;

I use default outgoing_body_buffer_chunks and outgoing_body_chunk_size in examples above

Expected Results

I think that if the body exceeds the outgoing parameter limits, call_handle should return an error instead of freezing.

Actual Results

TODO: What actually happens? Panic? Segfault? Incorrect result?

Versions and Environment

wasmtime = { version = "38", default-features = false }
wasmtime-wasi = { version = "38", default-features = false }
wasmtime-wasi-io = { version = "38", default-features = false }
wasmtime-wasi-http = { version = "38", default-features = false }

Extra Info

Anything else you'd like to add?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 08 2025 at 15:49):

if0ne added the bug label to Issue #12141.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 08 2025 at 18:11):

alexcrichton commented on issue #12141:

Thanks for the report! Would you be able to reduce this to a component which you could upload + a wasmtime serve invocation + a curl invocation? If the bug lies in Wasmtime I believe that should be a possible reproduction path.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 08 2025 at 21:29):

if0ne closed issue #12141:

Hi there!

If I try to return an array with a size of 2 MB, everything works fine:

use wasmcloud_component::http;

struct Component;

impl http::Server for Component {
    fn handle(
        _request: http::IncomingRequest,
    ) -> http::Result<http::Response<impl http::OutgoingBody>> {
        let mut bytes = vec![0u8; 2 * 1024 * 1024];
        Ok(http::Response::new(bytes))
    }
}

http::export!(Component);

Output:

curl localhost:8000 --output output.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 2048k    0 2048k    0     0  81.7M      0 --:--:-- --:--:-- --:--:-- 83.3M

But if I make the vector larger than 2 MB:

use wasmcloud_component::http;

struct Component;

impl http::Server for Component {
    fn handle(
        _request: http::IncomingRequest,
    ) -> http::Result<http::Response<impl http::OutgoingBody>> {
        let mut bytes = vec![0u8; 2 * 1024 * 1024 + 1];
        Ok(http::Response::new(bytes))
    }
}

http::export!(Component);

Output:

curl localhost:8000 --output output.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:01:55 --:--:--     0

I debugged the wasmCloud runtime and found that the code freezes on call_handle:

    let (sender, receiver) = tokio::sync::oneshot::channel();
    let scheme = match req.uri().scheme() {
        Some(scheme) if scheme == &hyper::http::uri::Scheme::HTTP => Scheme::Http,
        Some(scheme) if scheme == &hyper::http::uri::Scheme::HTTPS => Scheme::Https,
        Some(scheme) => Scheme::Other(scheme.as_str().to_string()),
        // Fallback to HTTP if no scheme is present
        None => Scheme::Http,
    };
    let req = store.data_mut().new_incoming_request(scheme, req)?;
    let out = store.data_mut().new_response_outparam(sender)?;
    let pre = ProxyPre::new(pre).context("failed to instantiate proxy pre")?;

    // Run the http request itself by instantiating and calling the component
    let proxy = pre.instantiate_async(&mut store).await?;

    proxy
        .wasi_http_incoming_handler()
        .call_handle(&mut store, req, out)
        .await?;

I use default outgoing_body_buffer_chunks and outgoing_body_chunk_size in examples above

Expected Results

I think that if the body exceeds the outgoing parameter limits, call_handle should return an error instead of freezing.

Actual Results

TODO: What actually happens? Panic? Segfault? Incorrect result?

Versions and Environment

wasmtime = { version = "38", default-features = false }
wasmtime-wasi = { version = "38", default-features = false }
wasmtime-wasi-io = { version = "38", default-features = false }
wasmtime-wasi-http = { version = "38", default-features = false }

Extra Info

Anything else you'd like to add?

view this post on Zulip Wasmtime GitHub notifications bot (Dec 08 2025 at 21:29):

if0ne commented on issue #12141:

I tested it using wasmtime serve. Everything works.

view this post on Zulip Wasmtime GitHub notifications bot (Dec 09 2025 at 11:30):

if0ne commented on issue #12141:

@alexcrichton the solution is to call call_handle in a separate tokio::task.


Last updated: Dec 13 2025 at 19:03 UTC