Prechádzať zdrojové kódy

fix(time): 处理信号中断导致的定时器唤醒 (#1204)

在sleep和schedule_timeout模块中增加信号中断检查,当定时器被信号中断时取消定时器并返回ERESTARTSYS错误。

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin 3 týždňov pred
rodič
commit
774f9eb7ce
2 zmenil súbory, kde vykonal 23 pridanie a 0 odobranie
  1. 17 0
      kernel/src/time/sleep.rs
  2. 6 0
      kernel/src/time/timer.rs

+ 17 - 0
kernel/src/time/sleep.rs

@@ -4,6 +4,7 @@ use alloc::{boxed::Box, sync::Arc};
 use system_error::SystemError;
 
 use crate::{
+    arch::ipc::signal::Signal,
     arch::{CurrentIrqArch, CurrentTimeArch},
     exception::InterruptArch,
     process::ProcessManager,
@@ -56,9 +57,25 @@ pub fn nanosleep(sleep_time: PosixTimeSpec) -> Result<PosixTimeSpec, SystemError
     schedule(SchedMode::SM_NONE);
 
     let end_time = getnstimeofday();
+
+    // 检查是否被信号中断,如果是则取消定时器
+    let current_pcb = ProcessManager::current_pcb();
+    let was_interrupted = current_pcb.has_pending_signal_fast()
+        || Signal::signal_pending_state(true, false, &current_pcb);
+
+    // 如果定时器没有超时(被信号中断或其他原因唤醒),则取消定时器
+    if !timer.timeout() {
+        timer.cancel();
+    }
+
     // 返回正确的剩余时间
     let real_sleep_time = end_time - start_time;
     let rm_time: PosixTimeSpec = (sleep_time - real_sleep_time.into()).into();
 
+    // 如果被信号中断,返回 ERESTARTSYS 错误
+    if was_interrupted {
+        return Err(SystemError::ERESTARTSYS);
+    }
+
     return Ok(rm_time);
 }

+ 6 - 0
kernel/src/time/timer.rs

@@ -325,6 +325,12 @@ pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
         drop(irq_guard);
 
         schedule(SchedMode::SM_NONE);
+
+        // 如果定时器没有超时(被信号中断或其他原因唤醒),则取消定时器
+        if !timer.timeout() {
+            timer.cancel();
+        }
+
         let time_remaining: i64 = timeout - TIMER_JIFFIES.load(Ordering::SeqCst) as i64;
         if time_remaining >= 0 {
             // 被提前唤醒,返回剩余时间