Skip to content

wasmtime_wasi_http call_handle freezes when outgoing body length exceeds outgoing_body_ limits* #12141

@if0ne

Description

@if0ne

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions