Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit d680050

Browse files
committed
implement new stream/future trap conditions
As of WebAssembly/component-model#524, we now trap if a guest tries to use a stream or future handle (besides dropping it) after it is "done" (see that PR for what "done" means). This required more careful tracking of the state of each end of the stream or future. In the process of debugging this into shape, I added some trace logging and addressed a couple of issues I noticed: - `wasi-http`'s `Response::into_http` wasn't noticing a non-empty buffer at the end of a stream - the `p3_http_middleware` test was not clearing its buffer before each read Signed-off-by: Joel Dice <[email protected]>
1 parent cfc95e7 commit d680050

File tree

13 files changed

+720
-104
lines changed

13 files changed

+720
-104
lines changed

Cargo.lock

Lines changed: 7 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,12 @@ lto = true
631631
# wasm-wave = { git = "https://github.com/bytecodealliance/wasm-tools" }
632632
# wasm-compose = { git = "https://github.com/bytecodealliance/wasm-tools" }
633633
# wasm-metadata = { git = "https://github.com/bytecodealliance/wasm-tools" }
634-
wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen" }
635-
wit-bindgen-rt = { git = "https://github.com/bytecodealliance/wit-bindgen" }
636-
wit-bindgen-rust-macro = { git = "https://github.com/bytecodealliance/wit-bindgen" }
634+
# wit-bindgen = { git = "https://github.com/bytecodealliance/wit-bindgen" }
635+
# wit-bindgen-rt = { git = "https://github.com/bytecodealliance/wit-bindgen" }
636+
# wit-bindgen-rust-macro = { git = "https://github.com/bytecodealliance/wit-bindgen" }
637+
wit-bindgen = { git = "https://github.com/dicej/wit-bindgen", branch = "no-reads-writes-after-dropped" }
638+
wit-bindgen-rt = { git = "https://github.com/dicej/wit-bindgen", branch = "no-reads-writes-after-dropped" }
639+
wit-bindgen-rust-macro = { git = "https://github.com/dicej/wit-bindgen", branch = "no-reads-writes-after-dropped" }
637640

638641
# wasmparser = { path = '../wasm-tools/crates/wasmparser' }
639642
# wat = { path = '../wasm-tools/crates/wat' }

crates/test-programs/src/bin/p3_http_middleware.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ impl Handler for Component {
6666
let remaining = pipe_tx.write_all(mem::take(decoder.get_mut())).await;
6767
assert!(remaining.is_empty());
6868
*decoder.get_mut() = remaining;
69+
chunk.clear();
6970
(status, chunk) = body.read(chunk).await;
7071
}
7172

crates/wasi-http/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ rustls = { workspace = true }
3434
webpki-roots = { workspace = true }
3535

3636
[dev-dependencies]
37+
env_logger = { workspace = true }
3738
test-programs-artifacts = { workspace = true }
3839
test-log = { workspace = true }
3940
tracing-subscriber = { workspace = true }

crates/wasi-http/src/p3/response.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,14 @@ impl Response {
214214
let fut = async move {
215215
loop {
216216
let (tail, mut rx_buffer) = contents.await;
217-
if let Some(tail) = tail {
218-
let buffer = rx_buffer.split();
219-
if !buffer.is_empty() {
220-
if let Err(..) = contents_tx.send(buffer.freeze()).await {
221-
break;
222-
}
223-
rx_buffer.reserve(DEFAULT_BUFFER_CAPACITY);
217+
let buffer = rx_buffer.split();
218+
if !buffer.is_empty() {
219+
if let Err(..) = contents_tx.send(buffer.freeze()).await {
220+
break;
224221
}
222+
rx_buffer.reserve(DEFAULT_BUFFER_CAPACITY);
223+
}
224+
if let Some(tail) = tail {
225225
contents = tail.read(rx_buffer).boxed();
226226
} else {
227227
debug_assert!(rx_buffer.is_empty());

crates/wasi-http/tests/all/p3/outgoing.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ foreach_p3_http!(assert_test_exists);
99
use super::proxy::{p3_http_echo, p3_http_middleware, p3_http_middleware_with_chain};
1010

1111
async fn run(path: &str, server: &Server) -> anyhow::Result<()> {
12+
_ = env_logger::try_init();
13+
1214
let engine = test_programs_artifacts::engine(|config| {
1315
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
1416
config.async_support(true);

crates/wasi-http/tests/all/p3/proxy.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ pub async fn p3_http_middleware_with_chain() -> Result<()> {
106106
}
107107

108108
async fn test_http_echo(component: &str, use_compression: bool) -> Result<()> {
109+
_ = env_logger::try_init();
110+
109111
let body = b"And the mome raths outgrabe";
110112

111113
// Prepare the raw body, optionally compressed if that's what we're

crates/wasi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ futures = { workspace = true }
3838
url = { workspace = true }
3939

4040
[dev-dependencies]
41+
env_logger = { workspace = true }
4142
tokio = { workspace = true, features = ["time", "sync", "io-std", "io-util", "rt", "rt-multi-thread", "net", "macros", "fs"] }
4243
test-log = { workspace = true }
4344
tracing-subscriber = { workspace = true }

crates/wasi/tests/all/p3/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ impl WasiSocketsView for Ctx {
104104
}
105105

106106
async fn run(path: &str) -> anyhow::Result<()> {
107+
_ = env_logger::try_init();
108+
107109
let path = Path::new(path);
108110
let engine = test_programs_artifacts::engine(|config| {
109111
config.async_support(true);

crates/wasmtime/src/runtime/component/concurrent.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4115,18 +4115,18 @@ impl Waitable {
41154115
assert_eq!(rep, self.rep());
41164116
assert_eq!(*state, StreamFutureState::Busy);
41174117
*state = match event {
4118-
Event::FutureRead { .. } => StreamFutureState::Read,
4119-
Event::FutureWrite { .. } => StreamFutureState::Write,
4118+
Event::FutureRead { .. } => StreamFutureState::Read { done: false },
4119+
Event::FutureWrite { .. } => StreamFutureState::Write { done: false },
41204120
_ => unreachable!(),
41214121
};
41224122
}
41234123
Event::StreamRead {
41244124
pending: Some((ty, handle)),
4125-
..
4125+
code,
41264126
}
41274127
| Event::StreamWrite {
41284128
pending: Some((ty, handle)),
4129-
..
4129+
code,
41304130
} => {
41314131
let runtime_instance = instance.component().types()[ty].instance;
41324132
let (rep, WaitableState::Stream(actual_ty, state)) = instance.waitable_tables()
@@ -4139,9 +4139,10 @@ impl Waitable {
41394139
assert_eq!(*actual_ty, ty);
41404140
assert_eq!(rep, self.rep());
41414141
assert_eq!(*state, StreamFutureState::Busy);
4142+
let done = matches!(code, ReturnCode::Dropped(_));
41424143
*state = match event {
4143-
Event::StreamRead { .. } => StreamFutureState::Read,
4144-
Event::StreamWrite { .. } => StreamFutureState::Write,
4144+
Event::StreamRead { .. } => StreamFutureState::Read { done },
4145+
Event::StreamWrite { .. } => StreamFutureState::Write { done },
41454146
_ => unreachable!(),
41464147
};
41474148
}

0 commit comments

Comments
 (0)