Browse Source

wasi: Handle read(0) with file streams (#8611)

* Test that wasi file streams can handle read(0)

* Zero-sized reads don't fail for file streams

* Accidentally removed the `read(0)` when refactoring the test
pull/8621/head
Trevor Elliott 6 months ago
committed by GitHub
parent
commit
aade0c86be
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 26
      crates/test-programs/src/bin/preview2_file_read_write.rs
  2. 7
      crates/wasi/src/filesystem.rs

26
crates/test-programs/src/bin/preview2_file_read_write.rs

@ -22,7 +22,31 @@ fn main() {
let stream = file.read_via_stream(0).unwrap();
let contents = stream.blocking_read(100).unwrap();
assert_eq!(contents, b"\0\0\0\0\0Hello, World!");
drop((stream, file));
drop(stream);
// Test that file read streams behave like other read streams.
let mut buf = Vec::new();
let stream = file.read_via_stream(0).unwrap();
let ready = stream.subscribe();
loop {
ready.block();
match stream.read(0) {
Ok(chunk) => assert!(chunk.is_empty()),
Err(wasi::io::streams::StreamError::Closed) => break,
Err(e) => panic!("Failed checking stream state: {e:?}"),
}
match stream.read(4) {
Ok(chunk) => buf.extend(chunk),
Err(wasi::io::streams::StreamError::Closed) => break,
Err(e) => panic!("Failed reading stream: {e:?}"),
}
}
assert_eq!(buf, b"\0\0\0\0\0Hello, World!");
drop(ready);
drop(stream);
drop(file);
dir.unlink_file_at(filename).unwrap();
}

7
crates/wasi/src/filesystem.rs

@ -248,6 +248,7 @@ impl FileInputStream {
pub async fn read(&mut self, size: usize) -> Result<Bytes, StreamError> {
use system_interface::fs::FileIoExt;
let p = self.position;
let (r, mut buf) = self
.file
.spawn_blocking(move |f| {
@ -256,7 +257,7 @@ impl FileInputStream {
(r, buf)
})
.await;
let n = read_result(r)?;
let n = read_result(r, size)?;
buf.truncate(n);
self.position += n as u64;
Ok(buf.freeze())
@ -268,9 +269,9 @@ impl FileInputStream {
}
}
fn read_result(r: io::Result<usize>) -> Result<usize, StreamError> {
fn read_result(r: io::Result<usize>, size: usize) -> Result<usize, StreamError> {
match r {
Ok(0) => Err(StreamError::Closed),
Ok(0) if size > 0 => Err(StreamError::Closed),
Ok(n) => Ok(n),
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => Ok(0),
Err(e) => Err(StreamError::LastOperationFailed(e.into())),

Loading…
Cancel
Save