Преглед на файлове

feat(syscall): 实现syscall restart (#1075)

能够在系统调用返回ERESTARTSYS时,信号处理结束后,自动重启系统调用.

TODO: 实现wait等需要restart_block的系统调用的重启

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin преди 4 месеца
родител
ревизия
2b72148cae

+ 2 - 1
kernel/Cargo.toml

@@ -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

+ 1 - 1
kernel/crates/system_error/Cargo.toml

@@ -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"

+ 32 - 12
kernel/crates/system_error/src/lib.rs

@@ -277,31 +277,51 @@ pub enum SystemError {
 
     // === 以下错误码不应该被用户态程序使用 ===
     ERESTARTSYS = 512,
+    ERESTARTNOINTR = 513,
+    /// restart if no handler
+    ERESTARTNOHAND = 514,
+
+    /// 没有对应的ioctlcmd
+    ENOIOCTLCMD = 515,
+    /// restart by calling sys restart syscall
+    ERESTART_RESTARTBLOCK = 516,
+
+    // === TODO: 这几个KVM的错误码不要放在这里 ===
+
     // VMX on 虚拟化开启指令出错
-    EVMXONFailed = 513,
+    EVMXONFailed = 1513,
     // VMX off 虚拟化关闭指令出错
-    EVMXOFFFailed = 514,
+    EVMXOFFFailed = 1514,
     // VMX VMWRITE 写入虚拟化VMCS内存出错
-    EVMWRITEFailed = 515,
-    EVMREADFailed = 516,
-    EVMPRTLDFailed = 517,
-    EVMLAUNCHFailed = 518,
-    KVM_HVA_ERR_BAD = 519,
-    /// 没有对应的ioctlcmd
-    ENOIOCTLCMD = 520,
+    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();
     }

+ 17 - 1
kernel/src/arch/riscv64/ipc/signal.rs

@@ -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!()
+    }
+}

+ 2 - 0
kernel/src/arch/riscv64/mod.rs

@@ -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;

+ 4 - 4
kernel/src/arch/x86_64/asm/entry.S

@@ -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
     

+ 27 - 0
kernel/src/arch/x86_64/interrupt/mod.rs

@@ -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 {

+ 151 - 79
kernel/src/arch/x86_64/ipc/signal.rs

@@ -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();
 
-pub struct X86_64SignalArch;
+    let siginfo = pcb.try_siginfo_irqsave(5);
 
-impl SignalArch for X86_64SignalArch {
-    unsafe fn do_signal(frame: &mut TrapFrame) {
-        let pcb = ProcessManager::current_pcb();
+    if unlikely(siginfo.is_none()) {
+        return;
+    }
 
-        let siginfo = pcb.try_siginfo_irqsave(5);
+    let siginfo_read_guard = siginfo.unwrap();
 
-        if unlikely(siginfo.is_none()) {
-            return;
-        }
+    // 检查sigpending是否为0
+    if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.is_from_user() {
+        // 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回
+        return;
+    }
 
-        let siginfo_read_guard = siginfo.unwrap();
+    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);
 
-        // 检查sigpending是否为0
-        if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.is_from_user() {
-            // 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回
-            return;
-        }
+    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 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 = sig_guard.unwrap();
+    let mut siginfo_mut_guard = siginfo_mut.unwrap();
+    loop {
+        (sig_number, info) = siginfo_mut_guard.dequeue_signal(&sig_block, &pcb);
 
-        let sig_guard = pcb.try_sig_struct_irqsave(5);
-        if unlikely(sig_guard.is_none()) {
+        // 如果信号非法,则直接返回
+        if sig_number == Signal::INVALID {
             return;
         }
-        let siginfo_mut = pcb.try_siginfo_mut(5);
-        if unlikely(siginfo_mut.is_none()) {
-            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!(),
         }
 
-        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;
-            }
+        if sigaction.is_some() {
+            break;
+        }
+    }
 
-            sigaction = sig_guard.handlers[sig_number as usize - 1];
+    let oldset = *siginfo_mut_guard.sig_blocked();
+    //避免死锁
+    drop(siginfo_mut_guard);
+    drop(sig_guard);
+    drop(pcb);
+    // 做完上面的检查后,开中断
+    CurrentIrqArch::interrupt_enable();
 
-            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!(),
-            }
-            // 如果当前动作是忽略这个信号,就继续循环。
+    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;
 
-        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()
-            );
+impl SignalArch for X86_64SignalArch {
+    /// 处理信号,并尝试重启系统调用
+    ///
+    /// 参考: 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);
+
+        if got_signal {
+            return;
         }
+        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);
 }

+ 2 - 0
kernel/src/arch/x86_64/syscall/mod.rs

@@ -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 {

+ 1 - 1
kernel/src/driver/tty/tty_device.rs

@@ -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);
             }
         }

+ 8 - 4
kernel/src/driver/tty/tty_job_control.rs

@@ -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);
             }
         }
 

+ 11 - 7
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -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) {

+ 46 - 0
kernel/src/exception/entry.rs

@@ -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();
+    }
+}

+ 1 - 0
kernel/src/exception/mod.rs

@@ -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;

+ 5 - 1
kernel/src/filesystem/eventfd.rs

@@ -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);
             }
 

+ 3 - 23
kernel/src/filesystem/vfs/file.rs

@@ -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

+ 4 - 1
kernel/src/ipc/pipe.rs

@@ -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);
             }
 

+ 77 - 18
kernel/src/ipc/signal.rs

@@ -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);

+ 11 - 5
kernel/src/ipc/signal_types.rs

@@ -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;
 }

+ 6 - 0
kernel/src/ipc/syscall.rs

@@ -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)
+    }
 }

+ 63 - 10
kernel/src/process/mod.rs

@@ -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,

+ 1 - 0
kernel/src/syscall/mod.rs

@@ -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),
         };
 

+ 3 - 1
user/apps/test-sigprocmask/main.c

@@ -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;
 

+ 1 - 0
user/apps/test_signal_restart/.gitignore

@@ -0,0 +1 @@
+test_signal

+ 20 - 0
user/apps/test_signal_restart/Makefile

@@ -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:

+ 106 - 0
user/apps/test_signal_restart/main.c

@@ -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);
+  }
+}

+ 41 - 0
user/dadk/config/test_signal_restart-0.1.0.toml

@@ -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]]部分