From aade0c86be23307d2486cd6dcaf070842f0e8f51 Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Tue, 14 May 2024 09:22:14 -0700 Subject: [PATCH] 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 --- .../src/bin/preview2_file_read_write.rs | 26 ++++++++++++++++++- crates/wasi/src/filesystem.rs | 7 ++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/test-programs/src/bin/preview2_file_read_write.rs b/crates/test-programs/src/bin/preview2_file_read_write.rs index 05a32a65b9..8c39d6de57 100644 --- a/crates/test-programs/src/bin/preview2_file_read_write.rs +++ b/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(); } diff --git a/crates/wasi/src/filesystem.rs b/crates/wasi/src/filesystem.rs index 197b2fe887..6b516ef025 100644 --- a/crates/wasi/src/filesystem.rs +++ b/crates/wasi/src/filesystem.rs @@ -248,6 +248,7 @@ impl FileInputStream { pub async fn read(&mut self, size: usize) -> Result { 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) -> Result { +fn read_result(r: io::Result, size: usize) -> Result { 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())),