Skip to content

Commit dceefcb

Browse files
committed
Fix handling of closed streams.
In Rust, `read` returning 0 bytes indicates end-of-stream, however in WASI a `read` returning 0 bytes has no special meaning. So special-case a 0 coming from WASI to report it to Rust differently. And, make writes on a closed WASI stream fail with `ConnectionReset`, indicating that the stream has been closed.
1 parent 8038a08 commit dceefcb

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

src/io/streams.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ impl AsyncRead for AsyncInputStream {
4040
// Ideally, the ABI would be able to read directly into buf. However, with the default
4141
// generated bindings, it returns a newly allocated vec, which we need to copy into buf.
4242
let read = match self.stream.read(buf.len() as u64) {
43+
// 0 bytets from WASI's `read` just means we got zero bytes.
44+
Ok(r) if r.is_empty() => {
45+
return Err(std::io::Error::from(std::io::ErrorKind::Interrupted))
46+
}
4347
Ok(r) => r,
48+
// 0 bytes from Rust's `read` means end-of-stream.
4449
Err(StreamError::Closed) => return Ok(0),
4550
Err(StreamError::LastOperationFailed(err)) => {
4651
return Err(std::io::Error::other(err.to_debug_string()))
@@ -97,13 +102,17 @@ impl AsyncWrite for AsyncOutputStream {
97102
let writable = some.try_into().unwrap_or(usize::MAX).min(buf.len());
98103
match self.stream.write(&buf[0..writable]) {
99104
Ok(()) => return Ok(writable),
100-
Err(StreamError::Closed) => return Ok(0),
105+
Err(StreamError::Closed) => {
106+
return Err(std::io::Error::from(std::io::ErrorKind::ConnectionReset))
107+
}
101108
Err(StreamError::LastOperationFailed(err)) => {
102109
return Err(std::io::Error::other(err.to_debug_string()))
103110
}
104111
}
105112
}
106-
Err(StreamError::Closed) => return Ok(0),
113+
Err(StreamError::Closed) => {
114+
return Err(std::io::Error::from(std::io::ErrorKind::ConnectionReset))
115+
}
107116
Err(StreamError::LastOperationFailed(err)) => {
108117
return Err(std::io::Error::other(err.to_debug_string()))
109118
}
@@ -116,7 +125,9 @@ impl AsyncWrite for AsyncOutputStream {
116125
self.ready().await;
117126
Ok(())
118127
}
119-
Err(StreamError::Closed) => Ok(()),
128+
Err(StreamError::Closed) => {
129+
Err(std::io::Error::from(std::io::ErrorKind::ConnectionReset))
130+
}
120131
Err(StreamError::LastOperationFailed(err)) => {
121132
Err(std::io::Error::other(err.to_debug_string()))
122133
}

0 commit comments

Comments
 (0)