diff --git a/src/libos/src/fs/file_table.rs b/src/libos/src/fs/file_table.rs index 75de0cee..5d5a1fca 100644 --- a/src/libos/src/fs/file_table.rs +++ b/src/libos/src/fs/file_table.rs @@ -21,6 +21,10 @@ impl FileTable { } } + pub fn table(&self) -> &Vec> { + &self.table + } + pub fn dup( &mut self, fd: FileDesc, diff --git a/src/libos/src/process/do_vfork.rs b/src/libos/src/process/do_vfork.rs index df1a64d8..d0af9d48 100644 --- a/src/libos/src/process/do_vfork.rs +++ b/src/libos/src/process/do_vfork.rs @@ -94,6 +94,10 @@ fn restore_parent_process(mut context: *mut CpuContext, current_ref: &ThreadRef) return_errno!(EFAULT, "couldn't restore parent file table"); } }; + + // Close all child opened files + close_files_opened_by_child(current_ref, &parent_file_table)?; + let mut current_file_table = current_ref.files().lock().unwrap(); *current_file_table = parent_file_table; @@ -131,3 +135,24 @@ pub fn check_vfork_for_exec(current_ref: &ThreadRef) -> Option<(ThreadId, Option None } } + +fn close_files_opened_by_child(current: &ThreadRef, parent_file_table: &FileTable) -> Result<()> { + let current_file_table = current.files().lock().unwrap(); + let child_open_fds: Vec = current_file_table + .table() + .iter() + .enumerate() + .filter(|(fd, _entry)| { + // Entry is only shown in the child file table + _entry.is_some() && parent_file_table.get_entry(*fd as FileDesc).is_err() + }) + .map(|(fd, entry)| fd as FileDesc) + .collect(); + + drop(current_file_table); + + child_open_fds + .iter() + .for_each(|&fd| current.close_file(fd).expect("close child file error")); + Ok(()) +}