Signal refactor (#402)

* 初步完成对 signal_types 和 部分signal代码的初始化

* 重构了一部分架构相关代码进入 arch 中

* 基本修改完成,编译通过,后续补上系统调用

* signal基本完成,能实现 Sigaction 系统调用

* 增加了一组枚举抽象

* 进一步重构了一部分C风格的代码

* 继续重构了一部分C风格代码

* 继续完善了一部分逻辑

* 修改了部分代码逻辑

* 补充了 fork 中复制信号信息的逻辑

* 修复了 kallsysms 未转义引号的问题

* 修复了无法跳转到 sigreturn 的bug

* 调通了 signal

* 实现了 signal 架构抽象层的 trait

* 为信号提供了默认处理函数

* 基本完成了 signal 的大体逻辑

* 修复了 Sigreturn 的一个小错误,格式化

* 修复了一个编译器漏报错误

* 删除了多余的代码

* 修改测试程序为链接 relibc

* 修复了信号处理过程中浮点寄存器错误保存的问题

* 修复了一个结构体错误引起的无法在relibc下正确运行的错误

* 修复了链接 relibc 时无法正常从信号处理返回的 bug

* 修复了 signal 处理流程中 rsp 指针错误导致的浮点运算触发GP

* 修复了一个死锁问题,解决了默认处理函数无法进入调度导致的bug

* 修复了一些错误

* 修改了 relibc 依赖版本号

* 删除了多余的 imports

* 删除一些debug日志

* 删除内核 signal.h 文件

* 删除一个依赖项

* 删除了 binding 相关依赖项
This commit is contained in:
Chiichen
2023-10-24 12:02:20 +08:00
committed by GitHub
parent d7f5742a20
commit 3c82aa56d1
29 changed files with 2353 additions and 261 deletions

View File

@ -1,8 +1,9 @@
use alloc::{string::ToString, sync::Arc};
use crate::{
arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid, libs::rwlock::RwLock,
process::ProcessFlags, syscall::SystemError,
arch::interrupt::TrapFrame, filesystem::procfs::procfs_register_pid,
ipc::signal::flush_signal_handlers, libs::rwlock::RwLock, process::ProcessFlags,
syscall::SystemError,
};
use super::{
@ -87,7 +88,13 @@ impl ProcessManager {
)
});
// todo: 拷贝信号相关数据
//拷贝信号相关数据
ProcessManager::copy_sighand(&clone_flags, &current_pcb, &pcb).unwrap_or_else(|e| {
panic!(
"fork: Failed to copy sighands from current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
current_pcb.pid(), pcb.pid(), e
)
});
// 拷贝线程
ProcessManager::copy_thread(&clone_flags, &current_pcb, &pcb, &current_trapframe).unwrap_or_else(|e| {
@ -194,11 +201,18 @@ impl ProcessManager {
#[allow(dead_code)]
fn copy_sighand(
_clone_flags: &CloneFlags,
_current_pcb: &Arc<ProcessControlBlock>,
_new_pcb: &Arc<ProcessControlBlock>,
clone_flags: &CloneFlags,
current_pcb: &Arc<ProcessControlBlock>,
new_pcb: &Arc<ProcessControlBlock>,
) -> Result<(), SystemError> {
// todo: 由于信号原来写的太烂,移植到新的进程管理的话,需要改动很多。因此决定重写。这里先空着
// // 将信号的处理函数设置为default(除了那些被手动屏蔽的)
if clone_flags.contains(CloneFlags::CLONE_CLEAR_SIGHAND) {
flush_signal_handlers(new_pcb.clone(), false);
}
if clone_flags.contains(CloneFlags::CLONE_SIGHAND) {
(*new_pcb.sig_struct()).handlers = current_pcb.sig_struct().handlers.clone();
}
return Ok(());
}
}

View File

@ -13,12 +13,18 @@ use alloc::{
use hashbrown::HashMap;
use crate::{
arch::{process::ArchPCBInfo, sched::sched, CurrentIrqArch},
arch::{
ipc::signal::{SigSet, Signal},
process::ArchPCBInfo,
sched::sched,
CurrentIrqArch,
},
exception::InterruptArch,
filesystem::{
procfs::procfs_unregister_pid,
vfs::{file::FileDescriptorVec, FileType},
},
ipc::signal_types::{SigInfo, SigPending, SignalStruct},
kdebug, kinfo,
libs::{
align::AlignedBox,
@ -34,7 +40,7 @@ use crate::{
SchedPolicy, SchedPriority,
},
smp::kick_cpu,
syscall::SystemError,
syscall::{Syscall, SystemError},
};
use self::kthread::WorkerPrivate;
@ -46,6 +52,7 @@ pub mod fork;
pub mod idle;
pub mod init;
pub mod kthread;
pub mod pid;
pub mod process;
pub mod syscall;
@ -184,6 +191,32 @@ impl ProcessManager {
}
}
/// 唤醒暂停的进程
pub fn wakeup_stop(pcb: &Arc<ProcessControlBlock>) -> Result<(), SystemError> {
let _guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
let state = pcb.sched_info().state();
if let ProcessState::Stopped = state {
let mut writer = pcb.sched_info_mut();
let state = writer.state();
if let ProcessState::Stopped = state {
writer.set_state(ProcessState::Runnable);
// avoid deadlock
drop(writer);
sched_enqueue(pcb.clone(), true);
return Ok(());
} else if state.is_runnable() {
return Ok(());
} else {
return Err(SystemError::EINVAL);
}
} else if state.is_runnable() {
return Ok(());
} else {
return Err(SystemError::EINVAL);
}
}
/// 标志当前进程永久睡眠,但是发起调度的工作,应该由调用者完成
///
/// ## 注意
@ -199,7 +232,7 @@ impl ProcessManager {
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info_mut_irqsave();
if writer.state() != ProcessState::Exited(0) {
if !matches!(writer.state(), ProcessState::Exited(_)) {
writer.set_state(ProcessState::Blocked(interruptable));
pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
drop(writer);
@ -209,6 +242,30 @@ impl ProcessManager {
return Err(SystemError::EINTR);
}
/// 标志当前进程为停止状态,但是发起调度的工作,应该由调用者完成
///
/// ## 注意
///
/// - 进入当前函数之前不能持有sched_info的锁
/// - 进入当前函数之前,必须关闭中断
pub fn mark_stop() -> Result<(), SystemError> {
assert_eq!(
CurrentIrqArch::is_irq_enabled(),
false,
"interrupt must be disabled before enter ProcessManager::mark_sleep()"
);
let pcb = ProcessManager::current_pcb();
let mut writer = pcb.sched_info_mut_irqsave();
if !matches!(writer.state(), ProcessState::Exited(_)) {
writer.set_state(ProcessState::Stopped);
pcb.flags().insert(ProcessFlags::NEED_SCHEDULE);
drop(writer);
return Ok(());
}
return Err(SystemError::EINTR);
}
/// 当子进程退出后向父进程发送通知
fn exit_notify() {
let current = ProcessManager::current_pcb();
@ -219,6 +276,19 @@ impl ProcessManager {
.adopt_childen()
.unwrap_or_else(|e| panic!("adopte_childen failed: error: {e:?}"))
};
let r = current.parent_pcb.read().upgrade();
if r.is_none() {
return;
}
let parent_pcb = r.unwrap();
let r = Syscall::kill(parent_pcb.pid(), Signal::SIGCHLD as i32);
if r.is_err() {
kwarn!(
"failed to send kill signal to {:?}'s parent pcb {:?}",
current.pid(),
parent_pcb.pid()
);
}
// todo: 当信号机制重写后这里需要向父进程发送SIGCHLD信号
}
}
@ -332,7 +402,7 @@ pub enum ProcessState {
/// - 如果该bool为false,那么这个进程必须被显式的唤醒才能重新进入Runnable状态。
Blocked(bool),
/// 进程被信号终止
// Stopped(SignalNumber),
Stopped,
/// 进程已经退出usize表示进程的退出码
Exited(usize),
}
@ -353,6 +423,14 @@ impl ProcessState {
pub fn is_exited(&self) -> bool {
return matches!(self, ProcessState::Exited(_));
}
/// Returns `true` if the process state is [`Stopped`].
///
/// [`Stopped`]: ProcessState::Stopped
#[inline(always)]
pub fn is_stopped(&self) -> bool {
matches!(self, ProcessState::Stopped)
}
}
bitflags! {
@ -395,6 +473,10 @@ pub struct ProcessControlBlock {
sched_info: RwLock<ProcessSchedulerInfo>,
/// 与处理器架构相关的信息
arch_info: SpinLock<ArchPCBInfo>,
/// 与信号处理相关的信息(似乎可以是无锁的)
sig_info: RwLock<ProcessSignalInfo>,
/// 信号处理结构体
sig_struct: SpinLock<SignalStruct>,
/// 父进程指针
parent_pcb: RwLock<Weak<ProcessControlBlock>>,
@ -460,6 +542,8 @@ impl ProcessControlBlock {
worker_private: SpinLock::new(None),
sched_info,
arch_info,
sig_info: RwLock::new(ProcessSignalInfo::default()),
sig_struct: SpinLock::new(SignalStruct::default()),
parent_pcb: RwLock::new(ppcb),
children: RwLock::new(HashMap::new()),
wait_queue: WaitQueue::INIT,
@ -638,6 +722,22 @@ impl ProcessControlBlock {
}
return name;
}
pub fn sig_info(&self) -> RwLockReadGuard<ProcessSignalInfo> {
self.sig_info.read()
}
pub fn sig_info_mut(&self) -> RwLockWriteGuard<ProcessSignalInfo> {
self.sig_info.write()
}
pub fn sig_struct(&self) -> SpinLockGuard<SignalStruct> {
self.sig_struct.lock()
}
pub fn sig_struct_irq(&self) -> SpinLockGuard<SignalStruct> {
self.sig_struct.lock_irqsave()
}
}
impl Drop for ProcessControlBlock {
@ -948,3 +1048,64 @@ impl Drop for KernelStack {
pub fn process_init() {
ProcessManager::init();
}
#[derive(Debug)]
pub struct ProcessSignalInfo {
// 当前进程
sig_block: SigSet,
// sig_pending 中存储当前线程要处理的信号
sig_pending: SigPending,
// sig_shared_pending 中存储当前线程所属进程要处理的信号
sig_shared_pending: SigPending,
}
impl ProcessSignalInfo {
pub fn sig_block(&self) -> &SigSet {
&self.sig_block
}
pub fn sig_pending(&self) -> &SigPending {
&self.sig_pending
}
pub fn sig_pending_mut(&mut self) -> &mut SigPending {
&mut self.sig_pending
}
pub fn sig_block_mut(&mut self) -> &mut SigSet {
&mut self.sig_block
}
pub fn sig_shared_pending_mut(&mut self) -> &mut SigPending {
&mut self.sig_shared_pending
}
pub fn sig_shared_pending(&self) -> &SigPending {
&self.sig_shared_pending
}
/// 从 pcb 的 siginfo中取出下一个要处理的信号先处理线程信号再处理进程信号
///
/// ## 参数
///
/// - `sig_mask` 被忽略掉的信号
///
pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
let res = self.sig_pending.dequeue_signal(sig_mask);
if res.0 != Signal::INVALID {
return res;
} else {
return self.sig_shared_pending.dequeue_signal(sig_mask);
}
}
}
impl Default for ProcessSignalInfo {
fn default() -> Self {
Self {
sig_block: SigSet::empty(),
sig_pending: SigPending::default(),
sig_shared_pending: SigPending::default(),
}
}
}

18
kernel/src/process/pid.rs Normal file
View File

@ -0,0 +1,18 @@
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum PidType {
/// pid类型是进程id
PID = 1,
TGID = 2,
PGID = 3,
SID = 4,
MAX = 5,
}
/// 为PidType实现判断相等的trait
impl PartialEq for PidType {
fn eq(&self, other: &PidType) -> bool {
*self as u8 == *other as u8
}
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "ptrace.h"
#include <DragonOS/signal.h>
#include <DragonOS/stdint.h>
// 进程最大可拥有的文件描述符数量

View File

@ -111,7 +111,7 @@ impl Syscall {
return Ok(0);
}
}
ProcessState::Blocked(_) => {
ProcessState::Blocked(_) | ProcessState::Stopped => {
// 指定WUNTRACED则等待暂停的进程不指定则返回0
if !options.contains(WaitOption::WUNTRACED)
|| options.contains(WaitOption::WNOWAIT)