fix: epoll drop deadlock and open AT_FDCWD with empty relative path panic (#1203)

* fix(epoll): 解决进程持有epoll_inode的时候exit导致的死锁问题

解决由于进程在进入exit流程之前,没有关闭epoll inode导致exit流程死锁的bug

Signed-off-by: longjin <longjin@DragonOS.org>

* fix(vfs): 解决AT_FDCWD时,传入path为空导致内核panic的问题

Signed-off-by: longjin <longjin@DragonOS.org>

* chore: 更新Held项目的git revision

将Held项目的git revision从f192df4更新为5163c56。

Signed-off-by: longjin <longjin@DragonOS.org>

---------

Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
LoGin
2025-06-14 17:32:15 +08:00
committed by GitHub
parent 2c6e9dee73
commit 8471e4173e
7 changed files with 45 additions and 18 deletions

View File

@ -1,3 +1,5 @@
use core::fmt::Debug;
use alloc::{ use alloc::{
string::{String, ToString}, string::{String, ToString},
sync::{Arc, Weak}, sync::{Arc, Weak},
@ -97,7 +99,6 @@ pub enum PtyType {
Pts, Pts,
} }
#[derive(Debug)]
#[cast_to([sync] Device)] #[cast_to([sync] Device)]
pub struct TtyDevice { pub struct TtyDevice {
name: String, name: String,
@ -144,6 +145,14 @@ impl TtyDevice {
} }
} }
impl Debug for TtyDevice {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TtyDevice")
.field("name", &self.name)
.finish()
}
}
impl PollableInode for TtyDevice { impl PollableInode for TtyDevice {
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> { fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
let tty = TtyDevice::tty_core(private_data)?; let tty = TtyDevice::tty_core(private_data)?;

View File

@ -68,16 +68,13 @@ impl EventPoll {
let fds: Vec<i32> = self.ep_items.keys().cloned().collect::<Vec<_>>(); let fds: Vec<i32> = self.ep_items.keys().cloned().collect::<Vec<_>>();
// 清理红黑树里面的epitems // 清理红黑树里面的epitems
for fd in fds { for fd in fds {
let file = ProcessManager::current_pcb() let fdtable = ProcessManager::current_pcb().basic().try_fd_table().clone();
.fd_table() let file = fdtable.and_then(|fdtable| fdtable.read().get_file_by_fd(fd));
.read()
.get_file_by_fd(fd);
if let Some(file) = file { if let Some(file) = file {
let epitm = self.ep_items.get(&fd).unwrap(); let epitm = self.ep_items.get(&fd).unwrap();
file.remove_epitem(epitm)?; file.remove_epitem(epitm)?;
} }
self.ep_items.remove(&fd); self.ep_items.remove(&fd);
} }
@ -644,7 +641,12 @@ impl EventPoll {
let epitems_guard = epitems.try_lock_irqsave()?; let epitems_guard = epitems.try_lock_irqsave()?;
for epitem in epitems_guard.iter() { for epitem in epitems_guard.iter() {
// The upgrade is safe because EventPoll always exists when the epitem is in the list // The upgrade is safe because EventPoll always exists when the epitem is in the list
let epoll = epitem.epoll().upgrade().unwrap(); let epoll = epitem.epoll().upgrade();
if epoll.is_none() {
// 如果epoll已经被释放则直接跳过
continue;
}
let epoll = epoll.unwrap();
let mut epoll_guard = epoll.try_lock()?; let mut epoll_guard = epoll.try_lock()?;
let binding = epitem.clone(); let binding = epitem.clone();
let event_guard = binding.event().read(); let event_guard = binding.event().read();

View File

@ -101,7 +101,6 @@ impl LockedFATFsInfo {
} }
} }
#[derive(Debug)]
pub struct FATInode { pub struct FATInode {
/// 指向父Inode的弱引用 /// 指向父Inode的弱引用
parent: Weak<LockedFATInode>, parent: Weak<LockedFATInode>,
@ -128,6 +127,14 @@ pub struct FATInode {
page_cache: Option<Arc<PageCache>>, page_cache: Option<Arc<PageCache>>,
} }
impl Debug for FATInode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FATInode")
.field("inode_id", &self.metadata.inode_id)
.finish()
}
}
impl FATInode { impl FATInode {
/// 将inode的元数据与磁盘同步 /// 将inode的元数据与磁盘同步
pub fn synchronize_metadata(&mut self) { pub fn synchronize_metadata(&mut self) {

View File

@ -45,7 +45,7 @@ pub fn user_path_at(
let mut inode = ROOT_INODE(); let mut inode = ROOT_INODE();
let ret_path; let ret_path;
// 如果path不是绝对路径则需要拼接 // 如果path不是绝对路径则需要拼接
if path.as_bytes()[0] != b'/' { if path.is_empty() || path.as_bytes()[0] != b'/' {
// 如果dirfd不是AT_FDCWD则需要检查dirfd是否是目录 // 如果dirfd不是AT_FDCWD则需要检查dirfd是否是目录
if dirfd != AtFlags::AT_FDCWD.bits() { if dirfd != AtFlags::AT_FDCWD.bits() {
let binding = pcb.fd_table(); let binding = pcb.fd_table();

View File

@ -291,14 +291,14 @@ impl ProcessManager {
) -> Result<(), SystemError> { ) -> Result<(), SystemError> {
// 如果不共享文件描述符表,则拷贝文件描述符表 // 如果不共享文件描述符表,则拷贝文件描述符表
if !clone_flags.contains(CloneFlags::CLONE_FILES) { if !clone_flags.contains(CloneFlags::CLONE_FILES) {
let new_fd_table = current_pcb.basic().fd_table().unwrap().read().clone(); let new_fd_table = current_pcb.basic().try_fd_table().unwrap().read().clone();
let new_fd_table = Arc::new(RwLock::new(new_fd_table)); let new_fd_table = Arc::new(RwLock::new(new_fd_table));
new_pcb.basic_mut().set_fd_table(Some(new_fd_table)); new_pcb.basic_mut().set_fd_table(Some(new_fd_table));
} else { } else {
// 如果共享文件描述符表,则直接拷贝指针 // 如果共享文件描述符表,则直接拷贝指针
new_pcb new_pcb
.basic_mut() .basic_mut()
.set_fd_table(current_pcb.basic().fd_table().clone()); .set_fd_table(current_pcb.basic().try_fd_table().clone());
} }
return Ok(()); return Ok(());

View File

@ -427,6 +427,7 @@ impl ProcessManager {
// 关中断 // 关中断
let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let pid: Pid; let pid: Pid;
{ {
let pcb = ProcessManager::current_pcb(); let pcb = ProcessManager::current_pcb();
@ -472,7 +473,6 @@ impl ProcessManager {
drop(thread); drop(thread);
unsafe { pcb.basic_mut().set_user_vm(None) }; unsafe { pcb.basic_mut().set_user_vm(None) };
pcb.exit_files(); pcb.exit_files();
// TODO 由于未实现进程组tty记录的前台进程组等于当前进程故退出前要置空 // TODO 由于未实现进程组tty记录的前台进程组等于当前进程故退出前要置空
// 后续相关逻辑需要在SYS_EXIT_GROUP系统调用中实现 // 后续相关逻辑需要在SYS_EXIT_GROUP系统调用中实现
if let Some(tty) = pcb.sig_info_irqsave().tty() { if let Some(tty) = pcb.sig_info_irqsave().tty() {
@ -483,7 +483,6 @@ impl ProcessManager {
} }
} }
pcb.sig_info_mut().set_tty(None); pcb.sig_info_mut().set_tty(None);
pcb.clear_pg_and_session_reference(); pcb.clear_pg_and_session_reference();
drop(pcb); drop(pcb);
ProcessManager::exit_notify(); ProcessManager::exit_notify();
@ -1048,7 +1047,7 @@ impl ProcessControlBlock {
/// 获取文件描述符表的Arc指针 /// 获取文件描述符表的Arc指针
#[inline(always)] #[inline(always)]
pub fn fd_table(&self) -> Arc<RwLock<FileDescriptorVec>> { pub fn fd_table(&self) -> Arc<RwLock<FileDescriptorVec>> {
return self.basic.read().fd_table().unwrap(); return self.basic.read().try_fd_table().unwrap();
} }
#[inline(always)] #[inline(always)]
@ -1218,7 +1217,12 @@ impl ProcessControlBlock {
/// Exit fd table when process exit /// Exit fd table when process exit
fn exit_files(&self) { fn exit_files(&self) {
self.basic.write_irqsave().set_fd_table(None); // 关闭文件描述符表
// 这里这样写的原因是避免某些inode在关闭时需要访问当前进程的basic导致死锁
let mut guard = self.basic.write_irqsave();
let old = guard.set_fd_table(None);
drop(guard);
drop(old)
} }
pub fn children_read_irqsave(&self) -> RwLockReadGuard<Vec<Pid>> { pub fn children_read_irqsave(&self) -> RwLockReadGuard<Vec<Pid>> {
@ -1369,12 +1373,17 @@ impl ProcessBasicInfo {
self.user_vm = user_vm; self.user_vm = user_vm;
} }
pub fn fd_table(&self) -> Option<Arc<RwLock<FileDescriptorVec>>> { pub fn try_fd_table(&self) -> Option<Arc<RwLock<FileDescriptorVec>>> {
return self.fd_table.clone(); return self.fd_table.clone();
} }
pub fn set_fd_table(&mut self, fd_table: Option<Arc<RwLock<FileDescriptorVec>>>) { pub fn set_fd_table(
&mut self,
fd_table: Option<Arc<RwLock<FileDescriptorVec>>>,
) -> Option<Arc<RwLock<FileDescriptorVec>>> {
let old = self.fd_table.take();
self.fd_table = fd_table; self.fd_table = fd_table;
return old;
} }
} }

View File

@ -25,7 +25,7 @@ source = "git"
source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/Held.git" source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/Held.git"
# git标签或分支 # git标签或分支
# 注意: branch和revision只能二选一且source要设置为"git" # 注意: branch和revision只能二选一且source要设置为"git"
revision = "f192df4" revision = "5163c56"
# 构建相关信息 # 构建相关信息
[build] [build]