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 = state.fs.get_fd(fd).ok();
39
40 if let Some(pfd) = fd_entry.as_ref()
44 && !pfd.is_stdio
45 && pfd.inode.is_preopened
46 {
47 trace!("Skipping fd_close for pre-opened FD ({})", fd);
48 return Ok(Errno::Success);
49 }
50 if fd <= __WASI_STDERR_FILENO {
52 match __asyncify_light(env, None, state.fs.flush(fd))? {
53 Ok(_) | Err(Errno::Isdir) | Err(Errno::Io) | Err(Errno::Access) => {}
54 Err(e) => {
55 return Ok(e);
56 }
57 }
58 wasi_try_ok!(state.fs.close_fd(fd));
59 } else {
60 let flush_target = fd_entry.as_ref().and_then(|fd_entry| {
64 let guard = fd_entry.inode.read();
65 match guard.deref() {
66 Kind::File {
67 handle: Some(file), ..
68 } => Some(file.clone()),
69 _ => None,
70 }
71 });
72
73 wasi_try_ok!(state.fs.close_fd(fd));
74
75 if let Some(file) = flush_target {
76 match __asyncify_light(env, None, FlushPoller { file })? {
77 Ok(_) | Err(Errno::Isdir) | Err(Errno::Io) | Err(Errno::Access) => {}
78 Err(e) => {
79 return Ok(e);
80 }
81 }
82 }
83 }
84
85 #[cfg(feature = "journal")]
86 if env.enable_journal {
87 JournalEffector::save_fd_close(&mut ctx, fd).map_err(|err| {
88 tracing::error!("failed to save close descriptor event - {}", err);
89 WasiError::Exit(ExitCode::from(Errno::Fault))
90 })?;
91 }
92
93 Ok(Errno::Success)
94}