Skip to content

Commit

Permalink
Fix for the non-flushing of file descriptors and a nasty deadlock
Browse files Browse the repository at this point in the history
  • Loading branch information
john-sharratt authored and theduke committed Nov 28, 2023
1 parent 7fbed59 commit 4fab39c
Showing 1 changed file with 31 additions and 39 deletions.
70 changes: 31 additions & 39 deletions lib/wasix/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,31 +460,26 @@ impl WasiFs {
/// Closes all the file handles.
#[allow(clippy::await_holding_lock)]
pub async fn close_all(&self) {
// TODO: this should close all uniquely owned files instead of just flushing.

if let Ok(mut map) = self.fd_map.write() {
map.clear();
}

let to_close = {
let mut to_close = {
if let Ok(map) = self.fd_map.read() {
map.keys().copied().collect::<Vec<_>>()
map.keys().copied().collect::<HashSet<_>>()
} else {
Vec::new()
HashSet::new()
}
};
to_close.insert(__WASI_STDOUT_FILENO);
to_close.insert(__WASI_STDERR_FILENO);

let _ = tokio::join!(
// Make sure the STDOUT and STDERR are explicitely flushed
self.flush(__WASI_STDOUT_FILENO),
self.flush(__WASI_STDERR_FILENO),
async {
for fd in to_close {
self.flush(fd).await.ok();
self.close_fd(fd).ok();
}
let _ = tokio::join!(async {
for fd in to_close {
self.flush(fd).await.ok();
self.close_fd(fd).ok();
}
);
});

if let Ok(mut map) = self.fd_map.write() {
map.clear();
}
}

/// Will conditionally union the binary file system with this one
Expand Down Expand Up @@ -1566,36 +1561,33 @@ impl WasiFs {
return Err(Errno::Access);
}

let work = {
let file = {
let guard = fd.inode.read();
match guard.deref() {
Kind::File {
handle: Some(file), ..
} => {
struct FlushPoller {
file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync>>>,
}
impl Future for FlushPoller {
type Output = Result<(), Errno>;
fn poll(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Self::Output> {
let mut file = self.file.write().unwrap();
Pin::new(file.as_mut())
.poll_flush(cx)
.map_err(|_| Errno::Io)
}
}
FlushPoller { file: file.clone() }
}
} => file.clone(),
// TODO: verify this behavior
Kind::Dir { .. } => return Err(Errno::Isdir),
Kind::Buffer { .. } => return Ok(()),
_ => return Err(Errno::Io),
}
};
work.await?
drop(fd);

struct FlushPoller {
file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync>>>,
}
impl Future for FlushPoller {
type Output = Result<(), Errno>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut file = self.file.write().unwrap();
Pin::new(file.as_mut())
.poll_flush(cx)
.map_err(|_| Errno::Io)
}
}
FlushPoller { file }.await?;
}
}
Ok(())
Expand Down

0 comments on commit 4fab39c

Please sign in to comment.