mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-26 23:33:22 +00:00
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:
@ -1,3 +1,5 @@
|
||||
use core::fmt::Debug;
|
||||
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
@ -97,7 +99,6 @@ pub enum PtyType {
|
||||
Pts,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cast_to([sync] Device)]
|
||||
pub struct TtyDevice {
|
||||
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 {
|
||||
fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
|
||||
let tty = TtyDevice::tty_core(private_data)?;
|
||||
|
@ -68,16 +68,13 @@ impl EventPoll {
|
||||
let fds: Vec<i32> = self.ep_items.keys().cloned().collect::<Vec<_>>();
|
||||
// 清理红黑树里面的epitems
|
||||
for fd in fds {
|
||||
let file = ProcessManager::current_pcb()
|
||||
.fd_table()
|
||||
.read()
|
||||
.get_file_by_fd(fd);
|
||||
let fdtable = ProcessManager::current_pcb().basic().try_fd_table().clone();
|
||||
let file = fdtable.and_then(|fdtable| fdtable.read().get_file_by_fd(fd));
|
||||
|
||||
if let Some(file) = file {
|
||||
let epitm = self.ep_items.get(&fd).unwrap();
|
||||
file.remove_epitem(epitm)?;
|
||||
}
|
||||
|
||||
self.ep_items.remove(&fd);
|
||||
}
|
||||
|
||||
@ -644,7 +641,12 @@ impl EventPoll {
|
||||
let epitems_guard = epitems.try_lock_irqsave()?;
|
||||
for epitem in epitems_guard.iter() {
|
||||
// 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 binding = epitem.clone();
|
||||
let event_guard = binding.event().read();
|
||||
|
@ -101,7 +101,6 @@ impl LockedFATFsInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FATInode {
|
||||
/// 指向父Inode的弱引用
|
||||
parent: Weak<LockedFATInode>,
|
||||
@ -128,6 +127,14 @@ pub struct FATInode {
|
||||
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 {
|
||||
/// 将inode的元数据与磁盘同步
|
||||
pub fn synchronize_metadata(&mut self) {
|
||||
|
@ -45,7 +45,7 @@ pub fn user_path_at(
|
||||
let mut inode = ROOT_INODE();
|
||||
let ret_path;
|
||||
// 如果path不是绝对路径,则需要拼接
|
||||
if path.as_bytes()[0] != b'/' {
|
||||
if path.is_empty() || path.as_bytes()[0] != b'/' {
|
||||
// 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
|
||||
if dirfd != AtFlags::AT_FDCWD.bits() {
|
||||
let binding = pcb.fd_table();
|
||||
|
@ -291,14 +291,14 @@ impl ProcessManager {
|
||||
) -> Result<(), SystemError> {
|
||||
// 如果不共享文件描述符表,则拷贝文件描述符表
|
||||
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));
|
||||
new_pcb.basic_mut().set_fd_table(Some(new_fd_table));
|
||||
} else {
|
||||
// 如果共享文件描述符表,则直接拷贝指针
|
||||
new_pcb
|
||||
.basic_mut()
|
||||
.set_fd_table(current_pcb.basic().fd_table().clone());
|
||||
.set_fd_table(current_pcb.basic().try_fd_table().clone());
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
|
@ -427,6 +427,7 @@ impl ProcessManager {
|
||||
|
||||
// 关中断
|
||||
let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||
|
||||
let pid: Pid;
|
||||
{
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
@ -472,7 +473,6 @@ impl ProcessManager {
|
||||
drop(thread);
|
||||
unsafe { pcb.basic_mut().set_user_vm(None) };
|
||||
pcb.exit_files();
|
||||
|
||||
// TODO 由于未实现进程组,tty记录的前台进程组等于当前进程,故退出前要置空
|
||||
// 后续相关逻辑需要在SYS_EXIT_GROUP系统调用中实现
|
||||
if let Some(tty) = pcb.sig_info_irqsave().tty() {
|
||||
@ -483,7 +483,6 @@ impl ProcessManager {
|
||||
}
|
||||
}
|
||||
pcb.sig_info_mut().set_tty(None);
|
||||
|
||||
pcb.clear_pg_and_session_reference();
|
||||
drop(pcb);
|
||||
ProcessManager::exit_notify();
|
||||
@ -1048,7 +1047,7 @@ impl ProcessControlBlock {
|
||||
/// 获取文件描述符表的Arc指针
|
||||
#[inline(always)]
|
||||
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)]
|
||||
@ -1218,7 +1217,12 @@ impl ProcessControlBlock {
|
||||
|
||||
/// Exit fd table when process exit
|
||||
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>> {
|
||||
@ -1369,12 +1373,17 @@ impl ProcessBasicInfo {
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ source = "git"
|
||||
source-path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/Held.git"
|
||||
# git标签或分支
|
||||
# 注意: branch和revision只能二选一,且source要设置为"git"
|
||||
revision = "f192df4"
|
||||
revision = "5163c56"
|
||||
|
||||
# 构建相关信息
|
||||
[build]
|
||||
|
Reference in New Issue
Block a user