wasmer_wasix/syscalls/wasi/
fd_close.rs1use super::*;
2use crate::fs::FlushPoller;
3use crate::syscalls::*;
4
5pub(crate) fn flush_captured_handle(
7 env: &WasiEnv,
8 flush_target: Option<
9 std::sync::Arc<std::sync::RwLock<Box<dyn virtual_fs::VirtualFile + Send + Sync>>>,
10 >,
11) -> Result<Errno, WasiError> {
12 let Some(file) = flush_target else {
13 return Ok(Errno::Success);
14 };
15
16 match __asyncify_light(env, None, FlushPoller { file })? {
17 Ok(_)
18 | Err(Errno::Isdir)
19 | Err(Errno::Io)
20 | Err(Errno::Access)
21 | Err(Errno::Inval) => Ok(Errno::Success),
23 Err(e) => Ok(e),
24 }
25}
26
27#[instrument(level = "trace", skip_all, fields(pid = ctx.data().process.pid().raw(), %fd), ret)]
39pub fn fd_close(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno, WasiError> {
40 WasiEnv::do_pending_operations(&mut ctx)?;
41
42 let env = ctx.data();
43 let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
44
45 let outcome = state.fs.close_fd_and_capture_flush(fd);
46
47 if outcome.skipped_preopen {
48 trace!("Skipping fd_close for pre-opened FD ({})", fd);
49 return Ok(Errno::Success);
50 }
51
52 if !outcome.removed {
53 return Ok(Errno::Badf);
54 }
55
56 flush_captured_handle(env, outcome.flush_target)?;
57
58 #[cfg(feature = "journal")]
59 if env.enable_journal {
60 JournalEffector::save_fd_close(&mut ctx, fd).map_err(|err| {
61 tracing::error!("failed to save close descriptor event - {}", err);
62 WasiError::Exit(ExitCode::from(Errno::Fault))
63 })?;
64 }
65
66 Ok(Errno::Success)
67}