wasmer_wasix/syscalls/wasi/
fd_close.rs1use super::*;
2use crate::syscalls::*;
3use std::{future::Future, pin::Pin, sync::Arc, task::Context, task::Poll};
4use virtual_fs::VirtualFile;
5
6struct FlushPoller {
7 file: Arc<std::sync::RwLock<Box<dyn VirtualFile + Send + Sync>>>,
8}
9
10impl Future for FlushPoller {
11 type Output = Result<(), Errno>;
12
13 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
14 let mut file = self.file.write().unwrap();
15 Pin::new(file.as_mut())
16 .poll_flush(cx)
17 .map_err(|_| Errno::Io)
18 }
19}
20
21#[instrument(level = "trace", skip_all, fields(pid = ctx.data().process.pid().raw(), %fd), ret)]
33pub fn fd_close(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno, WasiError> {
34 WasiEnv::do_pending_operations(&mut ctx)?;
35
36 let env = ctx.data();
37 let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
38 let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
39
40 if !fd_entry.is_stdio && fd_entry.inode.is_preopened {
44 trace!("Skipping fd_close for pre-opened FD ({})", fd);
45 return Ok(Errno::Success);
46 }
47 if fd <= __WASI_STDERR_FILENO {
49 match __asyncify_light(env, None, state.fs.flush(fd))? {
50 Ok(_) | Err(Errno::Isdir) | Err(Errno::Io) | Err(Errno::Access) => {}
51 Err(e) => {
52 return Ok(e);
53 }
54 }
55 wasi_try_ok!(state.fs.close_fd(fd));
56 } else {
57 let flush_target = {
61 let guard = fd_entry.inode.read();
62 match guard.deref() {
63 Kind::File {
64 handle: Some(file), ..
65 } => Some(file.clone()),
66 _ => None,
67 }
68 };
69
70 wasi_try_ok!(state.fs.close_fd(fd));
71
72 if let Some(file) = flush_target {
73 match __asyncify_light(env, None, FlushPoller { file })? {
74 Ok(_) | Err(Errno::Isdir) | Err(Errno::Io) | Err(Errno::Access) => {}
75 Err(e) => {
76 return Ok(e);
77 }
78 }
79 }
80 }
81
82 #[cfg(feature = "journal")]
83 if env.enable_journal {
84 JournalEffector::save_fd_close(&mut ctx, fd).map_err(|err| {
85 tracing::error!("failed to save close descriptor event - {}", err);
86 WasiError::Exit(ExitCode::from(Errno::Fault))
87 })?;
88 }
89
90 Ok(Errno::Success)
91}