feat(syscall): 实现syscall restart (#1075)
能够在系统调用返回ERESTARTSYS时,信号处理结束后,自动重启系统调用. TODO: 实现wait等需要restart_block的系统调用的重启 Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
parent
72423f90bb
commit
2b72148cae
|
@ -76,6 +76,7 @@ unwinding = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/unwi
|
|||
"panic",
|
||||
"personality"
|
||||
]}
|
||||
defer = "0.2.1"
|
||||
|
||||
# target为x86_64时,使用下面的依赖
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
|
@ -106,4 +107,4 @@ debug = true # Controls whether the compiler passes `-g`
|
|||
|
||||
# The release profile, used for `cargo build --release`
|
||||
[profile.release]
|
||||
debug = false
|
||||
debug = true
|
||||
|
|
|
@ -7,4 +7,4 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
|
||||
num-derive = "0.3"
|
||||
num-derive = "0.3"
|
||||
|
|
|
@ -277,31 +277,51 @@ pub enum SystemError {
|
|||
|
||||
// === 以下错误码不应该被用户态程序使用 ===
|
||||
ERESTARTSYS = 512,
|
||||
// VMX on 虚拟化开启指令出错
|
||||
EVMXONFailed = 513,
|
||||
// VMX off 虚拟化关闭指令出错
|
||||
EVMXOFFFailed = 514,
|
||||
// VMX VMWRITE 写入虚拟化VMCS内存出错
|
||||
EVMWRITEFailed = 515,
|
||||
EVMREADFailed = 516,
|
||||
EVMPRTLDFailed = 517,
|
||||
EVMLAUNCHFailed = 518,
|
||||
KVM_HVA_ERR_BAD = 519,
|
||||
ERESTARTNOINTR = 513,
|
||||
/// restart if no handler
|
||||
ERESTARTNOHAND = 514,
|
||||
|
||||
/// 没有对应的ioctlcmd
|
||||
ENOIOCTLCMD = 520,
|
||||
ENOIOCTLCMD = 515,
|
||||
/// restart by calling sys restart syscall
|
||||
ERESTART_RESTARTBLOCK = 516,
|
||||
|
||||
// === TODO: 这几个KVM的错误码不要放在这里 ===
|
||||
|
||||
// VMX on 虚拟化开启指令出错
|
||||
EVMXONFailed = 1513,
|
||||
// VMX off 虚拟化关闭指令出错
|
||||
EVMXOFFFailed = 1514,
|
||||
// VMX VMWRITE 写入虚拟化VMCS内存出错
|
||||
EVMWRITEFailed = 1515,
|
||||
EVMREADFailed = 1516,
|
||||
EVMPRTLDFailed = 1517,
|
||||
EVMLAUNCHFailed = 1518,
|
||||
KVM_HVA_ERR_BAD = 1519,
|
||||
|
||||
MAXERRNO = 4095,
|
||||
}
|
||||
|
||||
impl SystemError {
|
||||
/// @brief 把posix错误码转换为系统错误枚举类型。
|
||||
/// 判断一个值是否是有效的posix错误码。
|
||||
pub fn is_valid_posix_errno<T>(val: T) -> bool
|
||||
where
|
||||
T: PartialOrd + From<i32>,
|
||||
{
|
||||
let max_errno = T::from(-(Self::MAXERRNO as i32));
|
||||
val < T::from(0) && val >= max_errno
|
||||
}
|
||||
|
||||
/// 尝试把posix错误码转换为系统错误枚举类型。
|
||||
pub fn from_posix_errno(errno: i32) -> Option<SystemError> {
|
||||
// posix 错误码是小于0的
|
||||
if errno >= 0 {
|
||||
if !Self::is_valid_posix_errno(errno) {
|
||||
return None;
|
||||
}
|
||||
return <Self as num_traits::FromPrimitive>::from_i32(-errno);
|
||||
}
|
||||
|
||||
/// @brief 把系统错误枚举类型转换为负数posix错误码。
|
||||
/// 把系统错误枚举类型转换为负数posix错误码。
|
||||
pub fn to_posix_errno(&self) -> i32 {
|
||||
return -<Self as num_traits::ToPrimitive>::to_i32(self).unwrap();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use log::error;
|
||||
|
||||
use crate::{
|
||||
arch::{sched::sched, CurrentIrqArch},
|
||||
arch::{interrupt::TrapFrame, sched::sched, CurrentIrqArch},
|
||||
exception::InterruptArch,
|
||||
ipc::signal_types::SignalArch,
|
||||
process::ProcessManager,
|
||||
};
|
||||
|
||||
|
@ -339,3 +340,18 @@ fn sig_continue(sig: Signal) {
|
|||
fn sig_ignore(_sig: Signal) {
|
||||
return;
|
||||
}
|
||||
|
||||
pub struct RiscV64SignalArch;
|
||||
|
||||
impl SignalArch for RiscV64SignalArch {
|
||||
// TODO: 为RISCV64实现信号处理
|
||||
// 注意,rv64现在在中断/系统调用返回用户态时,没有进入 irqentry_exit() 函数,
|
||||
// 到时候实现信号处理时,需要修改中断/系统调用返回用户态的代码,进入 irqentry_exit() 函数
|
||||
unsafe fn do_signal_or_restart(_frame: &mut TrapFrame) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn sys_rt_sigreturn(_trap_frame: &mut TrapFrame) -> u64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ pub use self::time::RiscV64TimeArch as CurrentTimeArch;
|
|||
|
||||
pub use self::elf::RiscV64ElfArch as CurrentElfArch;
|
||||
|
||||
pub use self::ipc::signal::RiscV64SignalArch as CurrentSignalArch;
|
||||
|
||||
pub use crate::arch::smp::RiscV64SMPArch as CurrentSMPArch;
|
||||
|
||||
pub use crate::arch::sched::RiscV64SchedArch as CurrentSchedArch;
|
||||
|
|
|
@ -64,9 +64,9 @@ ENTRY(ret_from_intr)
|
|||
// 进入信号处理流程
|
||||
cli
|
||||
|
||||
// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
|
||||
// 将原本要返回的栈帧的栈指针传入irqentry_exit的第一个参数
|
||||
movq %rsp, %rdi
|
||||
callq do_signal
|
||||
callq irqentry_exit
|
||||
cli
|
||||
|
||||
__entry_ret_from_intr_before_gs_check_2:
|
||||
|
@ -375,10 +375,10 @@ ENTRY(syscall_64)
|
|||
sti
|
||||
callq *%rdx //调用服务程序
|
||||
|
||||
// 将原本要返回的栈帧的栈指针传入do_signal的第一个参数
|
||||
// 将原本要返回的栈帧的栈指针传入 irqentry_exit 的第一个参数
|
||||
movq %rsp, %rdi
|
||||
|
||||
callq do_signal
|
||||
callq irqentry_exit
|
||||
|
||||
cli
|
||||
|
||||
|
|
|
@ -125,6 +125,8 @@ pub struct TrapFrame {
|
|||
pub es: ::core::ffi::c_ulong,
|
||||
pub rax: ::core::ffi::c_ulong,
|
||||
pub func: ::core::ffi::c_ulong,
|
||||
/// - 该字段在异常发生时,保存的是错误码
|
||||
/// - 在系统调用时,由系统调用入口函数将其设置为系统调用号
|
||||
pub errcode: ::core::ffi::c_ulong,
|
||||
pub rip: ::core::ffi::c_ulong,
|
||||
pub cs: ::core::ffi::c_ulong,
|
||||
|
@ -182,6 +184,31 @@ impl TrapFrame {
|
|||
pub fn set_pc(&mut self, pc: usize) {
|
||||
self.rip = pc as u64;
|
||||
}
|
||||
|
||||
/// 获取系统调用号
|
||||
///
|
||||
/// # Safety
|
||||
/// 该函数只能在系统调用上下文中调用,
|
||||
/// 在其他上下文中,该函数返回值未定义
|
||||
pub unsafe fn syscall_nr(&self) -> Option<usize> {
|
||||
if self.errcode == u64::MAX {
|
||||
return None;
|
||||
}
|
||||
Some(self.errcode as usize)
|
||||
}
|
||||
|
||||
/// 获取系统调用错误码
|
||||
///
|
||||
/// # Safety
|
||||
/// 该函数只能在系统调用上下文中调用,
|
||||
/// 在其他上下文中,该函数返回值未定义
|
||||
///
|
||||
/// # Returns
|
||||
/// 返回一个 `Option<SystemError>`,表示系统调用的错误码。
|
||||
pub unsafe fn syscall_error(&self) -> Option<SystemError> {
|
||||
let val = self.rax as i32;
|
||||
SystemError::from_posix_errno(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl ProbeArgs for TrapFrame {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use core::{ffi::c_void, intrinsics::unlikely, mem::size_of};
|
||||
|
||||
use defer::defer;
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
|
@ -8,11 +9,12 @@ use crate::{
|
|||
fpu::FpState,
|
||||
interrupt::TrapFrame,
|
||||
process::table::{USER_CS, USER_DS},
|
||||
syscall::nr::SYS_RESTART_SYSCALL,
|
||||
CurrentIrqArch, MMArch,
|
||||
},
|
||||
exception::InterruptArch,
|
||||
ipc::{
|
||||
signal::set_current_blocked,
|
||||
signal::{restore_saved_sigmask, set_current_blocked},
|
||||
signal_types::{SaHandlerType, SigInfo, Sigaction, SigactionType, SignalArch},
|
||||
},
|
||||
mm::MemoryManagementArch,
|
||||
|
@ -405,99 +407,147 @@ pub struct SigStack {
|
|||
pub fpstate: FpState,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn do_signal(frame: &mut TrapFrame) {
|
||||
X86_64SignalArch::do_signal(frame);
|
||||
return;
|
||||
unsafe fn do_signal(frame: &mut TrapFrame, got_signal: &mut bool) {
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
|
||||
let siginfo = pcb.try_siginfo_irqsave(5);
|
||||
|
||||
if unlikely(siginfo.is_none()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let siginfo_read_guard = siginfo.unwrap();
|
||||
|
||||
// 检查sigpending是否为0
|
||||
if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.is_from_user() {
|
||||
// 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回
|
||||
return;
|
||||
}
|
||||
|
||||
let mut sig_number: Signal;
|
||||
let mut info: Option<SigInfo>;
|
||||
let mut sigaction: Option<Sigaction>;
|
||||
let sig_block: SigSet = *siginfo_read_guard.sig_blocked();
|
||||
drop(siginfo_read_guard);
|
||||
|
||||
let sig_guard = pcb.try_sig_struct_irqsave(5);
|
||||
if unlikely(sig_guard.is_none()) {
|
||||
return;
|
||||
}
|
||||
let siginfo_mut = pcb.try_siginfo_mut(5);
|
||||
if unlikely(siginfo_mut.is_none()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sig_guard = sig_guard.unwrap();
|
||||
let mut siginfo_mut_guard = siginfo_mut.unwrap();
|
||||
loop {
|
||||
(sig_number, info) = siginfo_mut_guard.dequeue_signal(&sig_block, &pcb);
|
||||
|
||||
// 如果信号非法,则直接返回
|
||||
if sig_number == Signal::INVALID {
|
||||
return;
|
||||
}
|
||||
let sa = sig_guard.handlers[sig_number as usize - 1];
|
||||
|
||||
match sa.action() {
|
||||
SigactionType::SaHandler(action_type) => match action_type {
|
||||
SaHandlerType::Error => {
|
||||
error!("Trying to handle a Sigerror on Process:{:?}", pcb.pid());
|
||||
return;
|
||||
}
|
||||
SaHandlerType::Default => {
|
||||
sigaction = Some(sa);
|
||||
}
|
||||
SaHandlerType::Ignore => continue,
|
||||
SaHandlerType::Customized(_) => {
|
||||
sigaction = Some(sa);
|
||||
}
|
||||
},
|
||||
SigactionType::SaSigaction(_) => todo!(),
|
||||
}
|
||||
|
||||
if sigaction.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let oldset = *siginfo_mut_guard.sig_blocked();
|
||||
//避免死锁
|
||||
drop(siginfo_mut_guard);
|
||||
drop(sig_guard);
|
||||
drop(pcb);
|
||||
// 做完上面的检查后,开中断
|
||||
CurrentIrqArch::interrupt_enable();
|
||||
|
||||
if sigaction.is_none() {
|
||||
return;
|
||||
}
|
||||
*got_signal = true;
|
||||
|
||||
let mut sigaction = sigaction.unwrap();
|
||||
|
||||
// 注意!由于handle_signal里面可能会退出进程,
|
||||
// 因此这里需要检查清楚:上面所有的锁、arc指针都被释放了。否则会产生资源泄露的问题!
|
||||
let res: Result<i32, SystemError> =
|
||||
handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame);
|
||||
if res.is_err() {
|
||||
error!(
|
||||
"Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
|
||||
sig_number as i32,
|
||||
ProcessManager::current_pcb().pid(),
|
||||
res.as_ref().unwrap_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn try_restart_syscall(frame: &mut TrapFrame) {
|
||||
defer!({
|
||||
// 如果没有信号需要传递,我们只需恢复保存的信号掩码
|
||||
restore_saved_sigmask();
|
||||
});
|
||||
|
||||
if unsafe { frame.syscall_nr() }.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let syscall_err = unsafe { frame.syscall_error() };
|
||||
if syscall_err.is_none() {
|
||||
return;
|
||||
}
|
||||
let syscall_err = syscall_err.unwrap();
|
||||
|
||||
let mut restart = false;
|
||||
match syscall_err {
|
||||
SystemError::ERESTARTSYS | SystemError::ERESTARTNOHAND | SystemError::ERESTARTNOINTR => {
|
||||
frame.rax = frame.errcode;
|
||||
frame.rip -= 2;
|
||||
restart = true;
|
||||
}
|
||||
SystemError::ERESTART_RESTARTBLOCK => {
|
||||
frame.rax = SYS_RESTART_SYSCALL as u64;
|
||||
frame.rip -= 2;
|
||||
restart = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
log::debug!("try restart syscall: {:?}", restart);
|
||||
}
|
||||
|
||||
pub struct X86_64SignalArch;
|
||||
|
||||
impl SignalArch for X86_64SignalArch {
|
||||
unsafe fn do_signal(frame: &mut TrapFrame) {
|
||||
let pcb = ProcessManager::current_pcb();
|
||||
/// 处理信号,并尝试重启系统调用
|
||||
///
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/signal.c#865
|
||||
unsafe fn do_signal_or_restart(frame: &mut TrapFrame) {
|
||||
let mut got_signal = false;
|
||||
do_signal(frame, &mut got_signal);
|
||||
|
||||
let siginfo = pcb.try_siginfo_irqsave(5);
|
||||
|
||||
if unlikely(siginfo.is_none()) {
|
||||
if got_signal {
|
||||
return;
|
||||
}
|
||||
|
||||
let siginfo_read_guard = siginfo.unwrap();
|
||||
|
||||
// 检查sigpending是否为0
|
||||
if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.is_from_user() {
|
||||
// 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回
|
||||
return;
|
||||
}
|
||||
|
||||
let mut sig_number: Signal;
|
||||
let mut info: Option<SigInfo>;
|
||||
let mut sigaction: Sigaction;
|
||||
let sig_block: SigSet = *siginfo_read_guard.sig_block();
|
||||
drop(siginfo_read_guard);
|
||||
|
||||
let sig_guard = pcb.try_sig_struct_irqsave(5);
|
||||
if unlikely(sig_guard.is_none()) {
|
||||
return;
|
||||
}
|
||||
let siginfo_mut = pcb.try_siginfo_mut(5);
|
||||
if unlikely(siginfo_mut.is_none()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sig_guard = sig_guard.unwrap();
|
||||
let mut siginfo_mut_guard = siginfo_mut.unwrap();
|
||||
loop {
|
||||
(sig_number, info) = siginfo_mut_guard.dequeue_signal(&sig_block);
|
||||
// 如果信号非法,则直接返回
|
||||
if sig_number == Signal::INVALID {
|
||||
return;
|
||||
}
|
||||
|
||||
sigaction = sig_guard.handlers[sig_number as usize - 1];
|
||||
|
||||
match sigaction.action() {
|
||||
SigactionType::SaHandler(action_type) => match action_type {
|
||||
SaHandlerType::Error => {
|
||||
error!("Trying to handle a Sigerror on Process:{:?}", pcb.pid());
|
||||
return;
|
||||
}
|
||||
SaHandlerType::Default => {
|
||||
sigaction = Sigaction::default();
|
||||
break;
|
||||
}
|
||||
SaHandlerType::Ignore => continue,
|
||||
SaHandlerType::Customized(_) => {
|
||||
break;
|
||||
}
|
||||
},
|
||||
SigactionType::SaSigaction(_) => todo!(),
|
||||
}
|
||||
// 如果当前动作是忽略这个信号,就继续循环。
|
||||
}
|
||||
|
||||
let oldset = *siginfo_mut_guard.sig_block();
|
||||
//避免死锁
|
||||
drop(siginfo_mut_guard);
|
||||
drop(sig_guard);
|
||||
drop(pcb);
|
||||
|
||||
// 做完上面的检查后,开中断
|
||||
CurrentIrqArch::interrupt_enable();
|
||||
|
||||
// 注意!由于handle_signal里面可能会退出进程,
|
||||
// 因此这里需要检查清楚:上面所有的锁、arc指针都被释放了。否则会产生资源泄露的问题!
|
||||
let res: Result<i32, SystemError> =
|
||||
handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame);
|
||||
if res.is_err() {
|
||||
error!(
|
||||
"Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
|
||||
sig_number as i32,
|
||||
ProcessManager::current_pcb().pid(),
|
||||
res.as_ref().unwrap_err()
|
||||
);
|
||||
}
|
||||
try_restart_syscall(frame);
|
||||
}
|
||||
|
||||
fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64 {
|
||||
|
@ -533,6 +583,8 @@ impl SignalArch for X86_64SignalArch {
|
|||
/// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
|
||||
///
|
||||
/// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
|
||||
///
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/signal.c#787
|
||||
fn handle_signal(
|
||||
sig: Signal,
|
||||
sigaction: &mut Sigaction,
|
||||
|
@ -540,8 +592,28 @@ fn handle_signal(
|
|||
oldset: &SigSet,
|
||||
frame: &mut TrapFrame,
|
||||
) -> Result<i32, SystemError> {
|
||||
// TODO 这里要补充一段逻辑,好像是为了保证引入线程之后的地址空间不会出问题。详见https://code.dragonos.org.cn/xref/linux-6.1.9/arch/mips/kernel/signal.c#830
|
||||
|
||||
if unsafe { frame.syscall_nr() }.is_some() {
|
||||
if let Some(syscall_err) = unsafe { frame.syscall_error() } {
|
||||
match syscall_err {
|
||||
SystemError::ERESTARTNOHAND | SystemError::ERESTART_RESTARTBLOCK => {
|
||||
frame.rax = SystemError::EINTR.to_posix_errno() as i64 as u64;
|
||||
}
|
||||
SystemError::ERESTARTSYS => {
|
||||
if !sigaction.flags().contains(SigFlags::SA_RESTART) {
|
||||
frame.rax = SystemError::EINTR.to_posix_errno() as i64 as u64;
|
||||
} else {
|
||||
frame.rax = frame.errcode;
|
||||
frame.rip -= 2;
|
||||
}
|
||||
}
|
||||
SystemError::ERESTARTNOINTR => {
|
||||
frame.rax = frame.errcode;
|
||||
frame.rip -= 2;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置栈帧
|
||||
return setup_frame(sig, sigaction, info, oldset, frame);
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ macro_rules! syscall_return {
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
|
||||
// 系统调用进入时,把系统调用号存入errcode字段,以便在syscall_handler退出后,仍能获取到系统调用号
|
||||
frame.errcode = frame.rax;
|
||||
let syscall_num = frame.rax as usize;
|
||||
// 防止sys_sched由于超时无法退出导致的死锁
|
||||
if syscall_num == SYS_SCHED {
|
||||
|
|
|
@ -263,7 +263,7 @@ impl IndexNode for TtyDevice {
|
|||
break;
|
||||
}
|
||||
|
||||
if pcb.sig_info_irqsave().sig_pending().has_pending() {
|
||||
if pcb.has_pending_signal_fast() {
|
||||
return Err(SystemError::ERESTARTSYS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use system_error::SystemError;
|
|||
use crate::{
|
||||
arch::ipc::signal::{SigSet, Signal},
|
||||
mm::VirtAddr,
|
||||
process::{Pid, ProcessManager},
|
||||
process::{Pid, ProcessFlags, ProcessManager},
|
||||
syscall::{
|
||||
user_access::{UserBufferReader, UserBufferWriter},
|
||||
Syscall,
|
||||
|
@ -51,9 +51,9 @@ impl TtyJobCtrlManager {
|
|||
if tty_pgid.is_some() && tty_pgid.unwrap() != pgid {
|
||||
if pcb
|
||||
.sig_info_irqsave()
|
||||
.sig_block()
|
||||
.sig_blocked()
|
||||
.contains(SigSet::from_bits_truncate(1 << sig as u64))
|
||||
|| pcb.sig_struct_irqsave().handlers[sig as usize].is_ignore()
|
||||
|| pcb.sig_struct_irqsave().handlers[sig as usize - 1].is_ignore()
|
||||
{
|
||||
// 忽略该信号
|
||||
if sig == Signal::SIGTTIN {
|
||||
|
@ -62,7 +62,11 @@ impl TtyJobCtrlManager {
|
|||
} else {
|
||||
// 暂时使用kill而不是killpg
|
||||
Syscall::kill(pgid, sig as i32)?;
|
||||
return Err(SystemError::ERESTART);
|
||||
ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
|
||||
return Err(SystemError::ERESTARTSYS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::EPollEventType,
|
||||
process::ProcessManager,
|
||||
process::{ProcessFlags, ProcessManager},
|
||||
syscall::{user_access::UserBufferWriter, Syscall},
|
||||
};
|
||||
|
||||
|
@ -1680,11 +1680,11 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
|||
break;
|
||||
}
|
||||
|
||||
if ProcessManager::current_pcb()
|
||||
.sig_info_irqsave()
|
||||
.sig_pending()
|
||||
.has_pending()
|
||||
{
|
||||
if ProcessManager::current_pcb().has_pending_signal_fast() {
|
||||
ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
|
||||
ret = Err(SystemError::ERESTARTSYS);
|
||||
break;
|
||||
}
|
||||
|
@ -1763,7 +1763,11 @@ impl TtyLineDiscipline for NTtyLinediscipline {
|
|||
// drop(ldata);
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
if pcb.sig_info_irqsave().sig_pending().has_pending() {
|
||||
if pcb.has_pending_signal_fast() {
|
||||
ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
|
||||
return Err(SystemError::ERESTARTSYS);
|
||||
}
|
||||
if core.flags().contains(TtyFlag::HUPPED) {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
use crate::{
|
||||
arch::{interrupt::TrapFrame, CurrentSignalArch},
|
||||
ipc::signal_types::SignalArch,
|
||||
process::{ProcessFlags, ProcessManager},
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn irqentry_exit(frame: &mut TrapFrame) {
|
||||
if frame.is_from_user() {
|
||||
irqentry_exit_to_user_mode(frame);
|
||||
}
|
||||
}
|
||||
|
||||
/// 退出到用户态之前,在这个函数内做最后的处理
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// 由于这个函数内可能会直接退出进程,因此,在进入函数之前,
|
||||
/// 必须保证所有的栈上的Arc/Box指针等,都已经被释放。否则,可能会导致内存泄漏。
|
||||
unsafe fn irqentry_exit_to_user_mode(frame: &mut TrapFrame) {
|
||||
exit_to_user_mode_prepare(frame);
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// 由于这个函数内可能会直接退出进程,因此,在进入函数之前,
|
||||
/// 必须保证所有的栈上的Arc/Box指针等,都已经被释放。否则,可能会导致内存泄漏。
|
||||
unsafe fn exit_to_user_mode_prepare(frame: &mut TrapFrame) {
|
||||
let process_flags_work = *ProcessManager::current_pcb().flags();
|
||||
if !process_flags_work.exit_to_user_mode_work().is_empty() {
|
||||
exit_to_user_mode_loop(frame, process_flags_work);
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// 由于这个函数内可能会直接退出进程,因此,在进入函数之前,
|
||||
/// 必须保证所有的栈上的Arc/Box指针等,都已经被释放。否则,可能会导致内存泄漏。
|
||||
unsafe fn exit_to_user_mode_loop(frame: &mut TrapFrame, mut process_flags_work: ProcessFlags) {
|
||||
while !process_flags_work.exit_to_user_mode_work().is_empty() {
|
||||
if process_flags_work.contains(ProcessFlags::HAS_PENDING_SIGNAL) {
|
||||
unsafe { CurrentSignalArch::do_signal_or_restart(frame) };
|
||||
}
|
||||
process_flags_work = *ProcessManager::current_pcb().flags();
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use crate::arch::CurrentIrqArch;
|
|||
pub mod debug;
|
||||
pub mod dummychip;
|
||||
pub mod ebreak;
|
||||
pub mod entry;
|
||||
pub mod handle;
|
||||
pub mod init;
|
||||
pub mod ipi;
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::filesystem::vfs::{FilePrivateData, FileSystem, FileType, IndexNode, M
|
|||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::libs::wait_queue::WaitQueue;
|
||||
use crate::net::event_poll::{EPollEventType, EPollItem, EventPoll, KernelIoctlData};
|
||||
use crate::process::ProcessManager;
|
||||
use crate::process::{ProcessFlags, ProcessManager};
|
||||
use crate::sched::SchedMode;
|
||||
use crate::syscall::Syscall;
|
||||
use alloc::collections::LinkedList;
|
||||
|
@ -127,6 +127,10 @@ impl IndexNode for EventFdInode {
|
|||
drop(lock_efd);
|
||||
let r = wq_wait_event_interruptible!(self.wait_queue, self.readable(), {});
|
||||
if r.is_err() {
|
||||
ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
|
||||
return Err(SystemError::ERESTARTSYS);
|
||||
}
|
||||
|
||||
|
|
|
@ -311,14 +311,7 @@ impl File {
|
|||
|
||||
let len = self
|
||||
.inode
|
||||
.read_at(offset, len, buf, self.private_data.lock())
|
||||
.map_err(|e| {
|
||||
if e == SystemError::ERESTARTSYS {
|
||||
SystemError::EINTR
|
||||
} else {
|
||||
e
|
||||
}
|
||||
})?;
|
||||
.read_at(offset, len, buf, self.private_data.lock())?;
|
||||
|
||||
if update_offset {
|
||||
self.offset
|
||||
|
@ -343,24 +336,11 @@ impl File {
|
|||
|
||||
// 如果文件指针已经超过了文件大小,则需要扩展文件大小
|
||||
if offset > self.inode.metadata()?.size as usize {
|
||||
self.inode.resize(offset).map_err(|e| {
|
||||
if e == SystemError::ERESTARTSYS {
|
||||
SystemError::EINTR
|
||||
} else {
|
||||
e
|
||||
}
|
||||
})?;
|
||||
self.inode.resize(offset)?;
|
||||
}
|
||||
let len = self
|
||||
.inode
|
||||
.write_at(offset, len, buf, self.private_data.lock())
|
||||
.map_err(|e| {
|
||||
if e == SystemError::ERESTARTSYS {
|
||||
SystemError::EINTR
|
||||
} else {
|
||||
e
|
||||
}
|
||||
})?;
|
||||
.write_at(offset, len, buf, self.private_data.lock())?;
|
||||
|
||||
if update_offset {
|
||||
self.offset
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
wait_queue::WaitQueue,
|
||||
},
|
||||
net::event_poll::{EPollEventType, EPollItem, EventPoll},
|
||||
process::{ProcessManager, ProcessState},
|
||||
process::{ProcessFlags, ProcessManager, ProcessState},
|
||||
sched::SchedMode,
|
||||
time::PosixTimeSpec,
|
||||
};
|
||||
|
@ -232,6 +232,9 @@ impl IndexNode for LockedPipeInode {
|
|||
drop(inode);
|
||||
let r = wq_wait_event_interruptible!(self.read_wait_queue, self.readable(), {});
|
||||
if r.is_err() {
|
||||
ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
return Err(SystemError::ERESTARTSYS);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ use crate::{
|
|||
arch::ipc::signal::{SigCode, SigFlags, SigSet, Signal},
|
||||
ipc::signal_types::SigactionType,
|
||||
libs::spinlock::SpinLockGuard,
|
||||
process::{pid::PidType, Pid, ProcessControlBlock, ProcessFlags, ProcessManager},
|
||||
process::{
|
||||
pid::PidType, Pid, ProcessControlBlock, ProcessFlags, ProcessManager, ProcessSignalInfo,
|
||||
},
|
||||
};
|
||||
|
||||
use super::signal_types::{
|
||||
|
@ -25,7 +27,7 @@ impl Signal {
|
|||
return false;
|
||||
}
|
||||
|
||||
if !pcb.has_pending_signal() {
|
||||
if !pcb.has_pending_signal_fast() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -112,7 +114,7 @@ impl Signal {
|
|||
}
|
||||
|
||||
if !self.prepare_sianal(pcb.clone(), force_send) {
|
||||
return Err(SystemError::EINVAL);
|
||||
return Ok(0);
|
||||
}
|
||||
// debug!("force send={}", force_send);
|
||||
let pcb_info = pcb.sig_info_irqsave();
|
||||
|
@ -213,13 +215,18 @@ impl Signal {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief 本函数用于检测指定的进程是否想要接收SIG这个信号。
|
||||
/// 本函数用于检测指定的进程是否想要接收SIG这个信号。
|
||||
///
|
||||
/// 当我们对于进程组中的所有进程都运行了这个检查之后,我们将可以找到组内愿意接收信号的进程。
|
||||
/// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。
|
||||
#[inline]
|
||||
fn wants_signal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
|
||||
// 如果改进程屏蔽了这个signal,则不能接收
|
||||
if pcb.sig_info_irqsave().sig_block().contains((*self).into()) {
|
||||
if pcb
|
||||
.sig_info_irqsave()
|
||||
.sig_blocked()
|
||||
.contains((*self).into())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -291,7 +298,7 @@ impl Signal {
|
|||
// 一个被阻塞了的信号肯定是要被处理的
|
||||
if pcb
|
||||
.sig_info_irqsave()
|
||||
.sig_block()
|
||||
.sig_blocked()
|
||||
.contains(self.into_sigset())
|
||||
{
|
||||
return true;
|
||||
|
@ -316,6 +323,7 @@ fn signal_wake_up(pcb: Arc<ProcessControlBlock>, _guard: SpinLockGuard<SignalStr
|
|||
// debug!("signal_wake_up");
|
||||
// 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
|
||||
let state = pcb.sched_info().inner_lock_read_irqsave().state();
|
||||
pcb.flags().insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
let mut wakeup_ok = true;
|
||||
if state.is_blocked_interruptable() {
|
||||
ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
|
||||
|
@ -350,16 +358,67 @@ fn signal_wake_up(pcb: Arc<ProcessControlBlock>, _guard: SpinLockGuard<SignalStr
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
|
||||
fn recalc_sigpending() {
|
||||
// todo:
|
||||
fn has_pending_signals(sigset: &SigSet, blocked: &SigSet) -> bool {
|
||||
sigset.bits() & (!blocked.bits()) != 0
|
||||
}
|
||||
|
||||
/// @brief 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为Default
|
||||
/// 除非某个信号被设置为ignore且force_default为false,否则都不会将其恢复
|
||||
impl ProcessControlBlock {
|
||||
/// 重新计算线程的flag中的TIF_SIGPENDING位
|
||||
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c?r=&mo=4806&fi=182#182
|
||||
pub fn recalc_sigpending(&self, siginfo_guard: Option<&ProcessSignalInfo>) {
|
||||
if !self.recalc_sigpending_tsk(siginfo_guard) {
|
||||
self.flags().remove(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
}
|
||||
}
|
||||
|
||||
fn recalc_sigpending_tsk(&self, siginfo_guard: Option<&ProcessSignalInfo>) -> bool {
|
||||
let mut _siginfo_tmp_guard = None;
|
||||
let siginfo = if let Some(siginfo_guard) = siginfo_guard {
|
||||
siginfo_guard
|
||||
} else {
|
||||
_siginfo_tmp_guard = Some(self.sig_info_irqsave());
|
||||
_siginfo_tmp_guard.as_ref().unwrap()
|
||||
};
|
||||
return siginfo.do_recalc_sigpending_tsk(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessSignalInfo {
|
||||
fn do_recalc_sigpending_tsk(&self, pcb: &ProcessControlBlock) -> bool {
|
||||
if has_pending_signals(&self.sig_pending().signal(), self.sig_blocked())
|
||||
|| has_pending_signals(&self.sig_shared_pending().signal(), self.sig_blocked())
|
||||
{
|
||||
pcb.flags().insert(ProcessFlags::HAS_PENDING_SIGNAL);
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* We must never clear the flag in another thread, or in current
|
||||
* when it's possible the current syscall is returning -ERESTART*.
|
||||
* So we don't clear it here, and only callers who know they should do.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/sched/signal.h?fi=restore_saved_sigmask#547
|
||||
pub fn restore_saved_sigmask() {
|
||||
if ProcessManager::current_pcb()
|
||||
.flags()
|
||||
.test_and_clear(ProcessFlags::RESTORE_SIG_MASK)
|
||||
{
|
||||
let saved = *ProcessManager::current_pcb()
|
||||
.sig_info_irqsave()
|
||||
.saved_sigmask();
|
||||
__set_current_blocked(&saved);
|
||||
}
|
||||
}
|
||||
|
||||
/// 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为默认状态。
|
||||
/// 除非某个信号被设置为忽略且 `force_default` 为 `false`,否则都不会将其恢复。
|
||||
///
|
||||
/// @param pcb 要被刷新的pcb
|
||||
/// @param force_default 是否强制将sigaction恢复成默认状态
|
||||
/// # 参数
|
||||
///
|
||||
/// - `pcb`: 要被刷新的pcb。
|
||||
/// - `force_default`: 是否强制将sigaction恢复成默认状态。
|
||||
pub fn flush_signal_handlers(pcb: Arc<ProcessControlBlock>, force_default: bool) {
|
||||
compiler_fence(core::sync::atomic::Ordering::SeqCst);
|
||||
// debug!("hand=0x{:018x}", hand as *const sighand_struct as usize);
|
||||
|
@ -467,7 +526,7 @@ fn __set_task_blocked(pcb: &Arc<ProcessControlBlock>, new_set: &SigSet) {
|
|||
if pcb.has_pending_signal() {
|
||||
let mut newblocked = *new_set;
|
||||
let guard = pcb.sig_info_irqsave();
|
||||
newblocked.remove(*guard.sig_block());
|
||||
newblocked.remove(*guard.sig_blocked());
|
||||
drop(guard);
|
||||
|
||||
// 从主线程开始去遍历
|
||||
|
@ -476,7 +535,7 @@ fn __set_task_blocked(pcb: &Arc<ProcessControlBlock>, new_set: &SigSet) {
|
|||
}
|
||||
}
|
||||
*pcb.sig_info_mut().sig_block_mut() = *new_set;
|
||||
recalc_sigpending();
|
||||
pcb.recalc_sigpending(None);
|
||||
}
|
||||
|
||||
fn __set_current_blocked(new_set: &SigSet) {
|
||||
|
@ -485,10 +544,10 @@ fn __set_current_blocked(new_set: &SigSet) {
|
|||
如果当前pcb的sig_blocked和新的相等,那么就不用改变它。
|
||||
请注意,一个进程的sig_blocked字段不能被其他进程修改!
|
||||
*/
|
||||
if pcb.sig_info_irqsave().sig_block().eq(new_set) {
|
||||
if pcb.sig_info_irqsave().sig_blocked().eq(new_set) {
|
||||
return;
|
||||
}
|
||||
let guard = pcb.sig_struct_irqsave();
|
||||
let guard: SpinLockGuard<'_, SignalStruct> = pcb.sig_struct_irqsave();
|
||||
|
||||
__set_task_blocked(&pcb, new_set);
|
||||
|
||||
|
@ -560,7 +619,7 @@ pub fn set_current_blocked(new_set: &mut SigSet) {
|
|||
pub fn set_sigprocmask(how: SigHow, set: SigSet) -> Result<SigSet, SystemError> {
|
||||
let pcb: Arc<ProcessControlBlock> = ProcessManager::current_pcb();
|
||||
let guard = pcb.sig_info_irqsave();
|
||||
let oset = *guard.sig_block();
|
||||
let oset = *guard.sig_blocked();
|
||||
|
||||
let mut res_set = oset;
|
||||
drop(guard);
|
||||
|
|
|
@ -75,9 +75,15 @@ pub struct InnerSignalStruct {
|
|||
impl SignalStruct {
|
||||
#[inline(never)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
let mut r = Self {
|
||||
inner: Box::<InnerSignalStruct>::default(),
|
||||
}
|
||||
};
|
||||
let sig_ign = Sigaction::default();
|
||||
r.inner.handlers[Signal::SIGCHLD as usize - 1] = sig_ign;
|
||||
r.inner.handlers[Signal::SIGURG as usize - 1] = sig_ign;
|
||||
r.inner.handlers[Signal::SIGWINCH as usize - 1] = sig_ign;
|
||||
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,8 +453,6 @@ impl SigPending {
|
|||
None
|
||||
};
|
||||
|
||||
// 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
|
||||
// recalc_sigpending();
|
||||
return (sig, info);
|
||||
}
|
||||
/// @brief 从sigpending中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
|
||||
|
@ -539,10 +543,12 @@ impl SigQueue {
|
|||
pub trait SignalArch {
|
||||
/// 信号处理函数
|
||||
///
|
||||
/// 处理信号或重启系统调用
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `frame` 中断栈帧
|
||||
unsafe fn do_signal(frame: &mut TrapFrame);
|
||||
unsafe fn do_signal_or_restart(frame: &mut TrapFrame);
|
||||
|
||||
fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64;
|
||||
}
|
||||
|
|
|
@ -567,4 +567,10 @@ impl Syscall {
|
|||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn restart_syscall() -> Result<usize, SystemError> {
|
||||
// todo: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c#2998
|
||||
unimplemented!("restart_syscall with restart block");
|
||||
// Err(SystemError::ENOSYS)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -612,6 +612,32 @@ bitflags! {
|
|||
const NEED_MIGRATE = 1 << 7;
|
||||
/// 随机化的虚拟地址空间,主要用于动态链接器的加载
|
||||
const RANDOMIZE = 1 << 8;
|
||||
/// 进程有未处理的信号(这是一个用于快速判断的标志位)
|
||||
/// 相当于Linux的TIF_SIGPENDING
|
||||
const HAS_PENDING_SIGNAL = 1 << 9;
|
||||
/// 进程需要恢复之前保存的信号掩码
|
||||
const RESTORE_SIG_MASK = 1 << 10;
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessFlags {
|
||||
pub const fn exit_to_user_mode_work(&self) -> Self {
|
||||
Self::from_bits_truncate(self.bits & (Self::HAS_PENDING_SIGNAL.bits))
|
||||
}
|
||||
|
||||
/// 测试并清除标志位
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - `rhs` : 需要测试并清除的标志位
|
||||
///
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 如果标志位在清除前是置位的,则返回 `true`,否则返回 `false`
|
||||
pub const fn test_and_clear(&mut self, rhs: Self) -> bool {
|
||||
let r = (self.bits & rhs.bits) != 0;
|
||||
self.bits &= !rhs.bits;
|
||||
r
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
|
@ -673,6 +699,7 @@ pub struct ProcessControlBlock {
|
|||
|
||||
/// 进程作为主体的凭证集
|
||||
cred: SpinLock<Cred>,
|
||||
self_ref: Weak<ProcessControlBlock>,
|
||||
}
|
||||
|
||||
impl ProcessControlBlock {
|
||||
|
@ -734,7 +761,7 @@ impl ProcessControlBlock {
|
|||
let ppcb: Weak<ProcessControlBlock> = ProcessManager::find(ppid)
|
||||
.map(|p| Arc::downgrade(&p))
|
||||
.unwrap_or_default();
|
||||
let pcb = Self {
|
||||
let mut pcb = Self {
|
||||
pid,
|
||||
tgid: pid,
|
||||
thread_pid: Arc::new(RwLock::new(PidStrcut::new())),
|
||||
|
@ -759,6 +786,7 @@ impl ProcessControlBlock {
|
|||
robust_list: RwLock::new(None),
|
||||
nsproxy: Arc::new(RwLock::new(NsProxy::new())),
|
||||
cred: SpinLock::new(cred),
|
||||
self_ref: Weak::new(),
|
||||
};
|
||||
|
||||
pcb.sig_info.write().set_tty(tty);
|
||||
|
@ -769,7 +797,10 @@ impl ProcessControlBlock {
|
|||
.lock()
|
||||
.init_syscall_stack(&pcb.syscall_stack.read());
|
||||
|
||||
let pcb = Arc::new(pcb);
|
||||
let pcb = Arc::new_cyclic(|weak| {
|
||||
pcb.self_ref = weak.clone();
|
||||
pcb
|
||||
});
|
||||
|
||||
pcb.sched_info()
|
||||
.sched_entity()
|
||||
|
@ -1017,6 +1048,11 @@ impl ProcessControlBlock {
|
|||
return has_pending;
|
||||
}
|
||||
|
||||
/// 根据 pcb 的 flags 判断当前进程是否有未处理的信号
|
||||
pub fn has_pending_signal_fast(&self) -> bool {
|
||||
self.flags.get().contains(ProcessFlags::HAS_PENDING_SIGNAL)
|
||||
}
|
||||
|
||||
pub fn sig_struct(&self) -> SpinLockGuard<SignalStruct> {
|
||||
self.sig_struct.lock_irqsave()
|
||||
}
|
||||
|
@ -1546,8 +1582,9 @@ pub fn process_init() {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessSignalInfo {
|
||||
// 当前进程
|
||||
sig_block: SigSet,
|
||||
// 当前进程被屏蔽的信号
|
||||
sig_blocked: SigSet,
|
||||
saved_sigmask: SigSet,
|
||||
// sig_pending 中存储当前线程要处理的信号
|
||||
sig_pending: SigPending,
|
||||
// sig_shared_pending 中存储当前线程所属进程要处理的信号
|
||||
|
@ -1557,8 +1594,8 @@ pub struct ProcessSignalInfo {
|
|||
}
|
||||
|
||||
impl ProcessSignalInfo {
|
||||
pub fn sig_block(&self) -> &SigSet {
|
||||
&self.sig_block
|
||||
pub fn sig_blocked(&self) -> &SigSet {
|
||||
&self.sig_blocked
|
||||
}
|
||||
|
||||
pub fn sig_pending(&self) -> &SigPending {
|
||||
|
@ -1570,7 +1607,15 @@ impl ProcessSignalInfo {
|
|||
}
|
||||
|
||||
pub fn sig_block_mut(&mut self) -> &mut SigSet {
|
||||
&mut self.sig_block
|
||||
&mut self.sig_blocked
|
||||
}
|
||||
|
||||
pub fn saved_sigmask(&self) -> &SigSet {
|
||||
&self.saved_sigmask
|
||||
}
|
||||
|
||||
pub fn saved_sigmask_mut(&mut self) -> &mut SigSet {
|
||||
&mut self.saved_sigmask
|
||||
}
|
||||
|
||||
pub fn sig_shared_pending_mut(&mut self) -> &mut SigPending {
|
||||
|
@ -1595,12 +1640,19 @@ impl ProcessSignalInfo {
|
|||
///
|
||||
/// - `sig_mask` 被忽略掉的信号
|
||||
///
|
||||
pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
|
||||
pub fn dequeue_signal(
|
||||
&mut self,
|
||||
sig_mask: &SigSet,
|
||||
pcb: &Arc<ProcessControlBlock>,
|
||||
) -> (Signal, Option<SigInfo>) {
|
||||
let res = self.sig_pending.dequeue_signal(sig_mask);
|
||||
pcb.recalc_sigpending(Some(self));
|
||||
if res.0 != Signal::INVALID {
|
||||
return res;
|
||||
} else {
|
||||
return self.sig_shared_pending.dequeue_signal(sig_mask);
|
||||
let res = self.sig_shared_pending.dequeue_signal(sig_mask);
|
||||
pcb.recalc_sigpending(Some(self));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1608,7 +1660,8 @@ impl ProcessSignalInfo {
|
|||
impl Default for ProcessSignalInfo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sig_block: SigSet::empty(),
|
||||
sig_blocked: SigSet::empty(),
|
||||
saved_sigmask: SigSet::empty(),
|
||||
sig_pending: SigPending::default(),
|
||||
sig_shared_pending: SigPending::default(),
|
||||
tty: None,
|
||||
|
|
|
@ -1217,6 +1217,7 @@ impl Syscall {
|
|||
Self::sys_perf_event_open(attr, pid, cpu, group_fd, flags)
|
||||
}
|
||||
SYS_SETRLIMIT => Ok(0),
|
||||
SYS_RESTART_SYSCALL => Self::restart_syscall(),
|
||||
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||
};
|
||||
|
||||
|
|
|
@ -62,9 +62,11 @@ int main() {
|
|||
perror("signal");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("Signal handler for SIGINT is registered.\n");
|
||||
signal_received = 0;
|
||||
kill(getpid(), SIGINT);
|
||||
sleep(5);
|
||||
|
||||
TEST_ASSERT(signal_received, 1, "SIGINT was received", "SIGINT was not received");
|
||||
signal_received = 0;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
test_signal
|
|
@ -0,0 +1,20 @@
|
|||
ifeq ($(ARCH), x86_64)
|
||||
CROSS_COMPILE=x86_64-linux-musl-
|
||||
else ifeq ($(ARCH), riscv64)
|
||||
CROSS_COMPILE=riscv64-linux-musl-
|
||||
endif
|
||||
|
||||
CC=$(CROSS_COMPILE)gcc
|
||||
|
||||
.PHONY: all
|
||||
all: main.c
|
||||
$(CC) -static -o test_signal_restart main.c
|
||||
|
||||
.PHONY: install clean
|
||||
install: all
|
||||
mv test_signal_restart $(DADK_CURRENT_BUILD_DIR)/test_signal_restart
|
||||
|
||||
clean:
|
||||
rm test_signal_restart *.o
|
||||
|
||||
fmt:
|
|
@ -0,0 +1,106 @@
|
|||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
#define MSG "Hello from parent!\n"
|
||||
|
||||
static int handled_signal = 0;
|
||||
// 子进程的信号处理函数
|
||||
void child_signal_handler(int sig) {
|
||||
printf("Child received signal %d\n", sig);
|
||||
handled_signal = 1;
|
||||
}
|
||||
|
||||
// 父进程的信号处理函数
|
||||
void parent_signal_handler(int sig) {
|
||||
printf("Parent received signal %d\n", sig);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int pipefd[2];
|
||||
pid_t pid;
|
||||
char buffer[BUFFER_SIZE];
|
||||
|
||||
// 创建管道
|
||||
if (pipe(pipefd) == -1) {
|
||||
perror("pipe");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// 创建子进程
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
// 子进程
|
||||
close(pipefd[1]); // 关闭写端
|
||||
|
||||
// 设置子进程的信号处理函数
|
||||
signal(SIGUSR1, child_signal_handler);
|
||||
|
||||
printf("Child: Waiting for data...\n");
|
||||
|
||||
// 尝试从管道中读取数据
|
||||
ssize_t bytes_read = read(pipefd[0], buffer, BUFFER_SIZE - 1);
|
||||
if (bytes_read == -1) {
|
||||
printf("[FAILED]: Child: read error, errno=%d\n", errno);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (bytes_read == 0) {
|
||||
printf("Child: End of file\n");
|
||||
}
|
||||
|
||||
if (bytes_read != sizeof(MSG) - 1) {
|
||||
printf("[FAILED]: Child: read error: got %ld bytes, expected %ld\n",
|
||||
bytes_read, sizeof(MSG) - 1);
|
||||
} else {
|
||||
printf("[PASS]: Child: read success: got %ld bytes, expected %ld\n",
|
||||
bytes_read, sizeof(MSG) - 1);
|
||||
}
|
||||
|
||||
buffer[bytes_read] = '\0';
|
||||
printf("Child: Received message: %s", buffer);
|
||||
|
||||
close(pipefd[0]);
|
||||
|
||||
if (!handled_signal)
|
||||
printf("[FAILED]: Parent: child did not handle signal\n");
|
||||
else
|
||||
printf("[PASS]: Parent: child handled signal\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
// 父进程
|
||||
close(pipefd[0]); // 关闭读端
|
||||
|
||||
// 设置父进程的信号处理函数
|
||||
signal(SIGCHLD, parent_signal_handler);
|
||||
|
||||
// 发送信号给子进程,中断它的读操作
|
||||
sleep(1); // 确保子进程已经开始读取
|
||||
// printf("Parent: Sending SIGCHLD to child...\n");
|
||||
// kill(pid, SIGCHLD);
|
||||
printf("Parent: Sending SIGUSR1 to child...\n");
|
||||
kill(pid, SIGUSR1);
|
||||
sleep(1); // 确保子进程已经处理了信号
|
||||
|
||||
write(pipefd[1], MSG, strlen(MSG));
|
||||
|
||||
printf("Parent: Sent message: %s", MSG);
|
||||
|
||||
// 等待子进程结束
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
printf("Parent: Child process finished.\n");
|
||||
|
||||
close(pipefd[1]);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
# 用户程序名称
|
||||
name = "test_signal_restart"
|
||||
# 版本号
|
||||
version = "0.1.0"
|
||||
# 用户程序描述信息
|
||||
description = "一个用来测试signal能够正常运行的app"
|
||||
# (可选)默认: false 是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果
|
||||
build-once = false
|
||||
# (可选) 默认: false 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装
|
||||
install-once = false
|
||||
# 目标架构
|
||||
# 可选值:"x86_64", "aarch64", "riscv64"
|
||||
target-arch = ["x86_64"]
|
||||
# 任务源
|
||||
[task-source]
|
||||
# 构建类型
|
||||
# 可选值:"build-from_source", "install-from-prebuilt"
|
||||
type = "build-from-source"
|
||||
# 构建来源
|
||||
# "build_from_source" 可选值:"git", "local", "archive"
|
||||
# "install_from_prebuilt" 可选值:"local", "archive"
|
||||
source = "local"
|
||||
# 路径或URL
|
||||
source-path = "user/apps/test_signal_restart"
|
||||
# 构建相关信息
|
||||
[build]
|
||||
# (可选)构建命令
|
||||
build-command = "make install"
|
||||
# 安装相关信息
|
||||
[install]
|
||||
# (可选)安装到DragonOS的路径
|
||||
in-dragonos-path = "/bin"
|
||||
# 清除相关信息
|
||||
[clean]
|
||||
# (可选)清除命令
|
||||
clean-command = "make clean"
|
||||
# (可选)依赖项
|
||||
# 注意:如果没有依赖项,忽略此项,不允许只留一个[[depends]]
|
||||
# 由于原文件中依赖项为空,此处省略[[depends]]部分
|
||||
# (可选)环境变量
|
||||
# 由于原文件中环境变量为空,此处省略[[envs]]部分
|
Loading…
Reference in New Issue