xref: /DragonOS/kernel/src/ipc/signal_types.rs (revision 86ee1395de7c614865236ee15071c3603b794e44)
1 use core::{
2     ffi::c_void,
3     mem::size_of,
4     ops::{Deref, DerefMut},
5     sync::atomic::AtomicI64,
6 };
7 
8 use alloc::{boxed::Box, vec::Vec};
9 use system_error::SystemError;
10 
11 use crate::{
12     arch::{
13         asm::bitops::ffz,
14         interrupt::TrapFrame,
15         ipc::signal::{SigCode, SigFlags, SigSet, Signal, MAX_SIG_NUM},
16     },
17     mm::VirtAddr,
18     process::Pid,
19     syscall::user_access::UserBufferWriter,
20 };
21 
22 /// 用户态程序传入的SIG_DFL的值
23 pub const USER_SIG_DFL: u64 = 0;
24 /// 用户态程序传入的SIG_IGN的值
25 pub const USER_SIG_IGN: u64 = 1;
26 /// 用户态程序传入的SIG_ERR的值
27 pub const USER_SIG_ERR: u64 = 2;
28 
29 // 因为 Rust 编译器不能在常量声明中正确识别级联的 "|" 运算符(experimental feature: https://github.com/rust-lang/rust/issues/67792),因此
30 // 暂时只能通过这种方法来声明这些常量,这些常量暂时没有全部用到,但是都出现在 linux 的判断逻辑中,所以都保留下来了
31 #[allow(dead_code)]
32 pub const SIG_KERNEL_ONLY_MASK: SigSet =
33     Signal::into_sigset(Signal::SIGSTOP).union(Signal::into_sigset(Signal::SIGKILL));
34 
35 pub const SIG_KERNEL_STOP_MASK: SigSet = Signal::into_sigset(Signal::SIGSTOP)
36     .union(Signal::into_sigset(Signal::SIGTSTP))
37     .union(Signal::into_sigset(Signal::SIGTTIN))
38     .union(Signal::into_sigset(Signal::SIGTTOU));
39 #[allow(dead_code)]
40 pub const SIG_KERNEL_COREDUMP_MASK: SigSet = Signal::into_sigset(Signal::SIGQUIT)
41     .union(Signal::into_sigset(Signal::SIGILL))
42     .union(Signal::into_sigset(Signal::SIGTRAP))
43     .union(Signal::into_sigset(Signal::SIGABRT_OR_IOT))
44     .union(Signal::into_sigset(Signal::SIGFPE))
45     .union(Signal::into_sigset(Signal::SIGSEGV))
46     .union(Signal::into_sigset(Signal::SIGBUS))
47     .union(Signal::into_sigset(Signal::SIGSYS))
48     .union(Signal::into_sigset(Signal::SIGXCPU))
49     .union(Signal::into_sigset(Signal::SIGXFSZ));
50 #[allow(dead_code)]
51 pub const SIG_KERNEL_IGNORE_MASK: SigSet = Signal::into_sigset(Signal::SIGCONT)
52     .union(Signal::into_sigset(Signal::SIGFPE))
53     .union(Signal::into_sigset(Signal::SIGSEGV))
54     .union(Signal::into_sigset(Signal::SIGBUS))
55     .union(Signal::into_sigset(Signal::SIGTRAP))
56     .union(Signal::into_sigset(Signal::SIGCHLD))
57     .union(Signal::into_sigset(Signal::SIGIO_OR_POLL))
58     .union(Signal::into_sigset(Signal::SIGSYS));
59 
60 /// SignalStruct 在 pcb 中加锁
61 #[derive(Debug)]
62 pub struct SignalStruct {
63     inner: Box<InnerSignalStruct>,
64 }
65 
66 #[derive(Debug)]
67 #[allow(dead_code)]
68 pub struct InnerSignalStruct {
69     pub cnt: AtomicI64,
70     /// 如果对应linux,这部分会有一个引用计数,但是没发现在哪里有用到需要计算引用的地方,因此
71     /// 暂时删掉,不然这个Arc会导致其他地方的代码十分丑陋
72     pub handlers: [Sigaction; MAX_SIG_NUM],
73 }
74 
75 impl SignalStruct {
76     #[inline(never)]
77     pub fn new() -> Self {
78         Self {
79             inner: Box::<InnerSignalStruct>::default(),
80         }
81     }
82 }
83 
84 impl Deref for SignalStruct {
85     type Target = InnerSignalStruct;
86 
87     fn deref(&self) -> &Self::Target {
88         &self.inner
89     }
90 }
91 
92 impl DerefMut for SignalStruct {
93     fn deref_mut(&mut self) -> &mut Self::Target {
94         &mut self.inner
95     }
96 }
97 
98 impl Default for InnerSignalStruct {
99     fn default() -> Self {
100         Self {
101             cnt: Default::default(),
102             handlers: [Sigaction::default(); MAX_SIG_NUM],
103         }
104     }
105 }
106 
107 #[derive(Debug, Copy, Clone)]
108 #[allow(dead_code)]
109 pub enum SigactionType {
110     SaHandler(SaHandlerType),
111     SaSigaction(
112         Option<
113             unsafe extern "C" fn(
114                 sig: ::core::ffi::c_int,
115                 sinfo: *mut SigInfo,
116                 arg1: *mut ::core::ffi::c_void,
117             ),
118         >,
119     ), // 暂时没有用上
120 }
121 
122 impl SigactionType {
123     /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigIgnore)`].
124     ///
125     /// [`SigIgnore`]: SaHandlerType::SigIgnore
126     pub fn is_ignore(&self) -> bool {
127         return matches!(self, Self::SaHandler(SaHandlerType::Ignore));
128     }
129     /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigCustomized(_))`].
130     ///
131     /// [`SigCustomized`]: SaHandlerType::SigCustomized(_)
132     pub fn is_customized(&self) -> bool {
133         return matches!(self, Self::SaHandler(SaHandlerType::Customized(_)));
134     }
135 }
136 
137 #[derive(Debug, Copy, Clone)]
138 #[allow(dead_code)]
139 pub enum SaHandlerType {
140     Error, // 暂时没有用上
141     Default,
142     Ignore,
143     Customized(VirtAddr),
144 }
145 
146 impl From<SaHandlerType> for usize {
147     fn from(value: SaHandlerType) -> Self {
148         match value {
149             SaHandlerType::Error => 2,
150             SaHandlerType::Ignore => 1,
151             SaHandlerType::Default => 0,
152             SaHandlerType::Customized(handler) => handler.data(),
153         }
154     }
155 }
156 
157 impl SaHandlerType {
158     /// Returns `true` if the sa handler type is [`SigDefault`].
159     ///
160     /// [`SigDefault`]: SaHandlerType::SigDefault
161     pub fn is_sig_default(&self) -> bool {
162         matches!(self, Self::Default)
163     }
164 
165     /// Returns `true` if the sa handler type is [`SigIgnore`].
166     ///
167     /// [`SigIgnore`]: SaHandlerType::SigIgnore
168     pub fn is_sig_ignore(&self) -> bool {
169         matches!(self, Self::Ignore)
170     }
171 
172     /// Returns `true` if the sa handler type is [`SigError`].
173     ///
174     /// [`SigError`]: SaHandlerType::SigError
175     pub fn is_sig_error(&self) -> bool {
176         matches!(self, Self::Error)
177     }
178 }
179 
180 /// 信号处理结构体
181 ///
182 #[derive(Debug, Copy, Clone)]
183 pub struct Sigaction {
184     action: SigactionType,
185     flags: SigFlags,
186     mask: SigSet, // 为了可扩展性而设置的sa_mask
187     /// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
188     restorer: Option<VirtAddr>,
189 }
190 
191 impl Default for Sigaction {
192     fn default() -> Self {
193         Self {
194             action: SigactionType::SaHandler(SaHandlerType::Default),
195             flags: Default::default(),
196             mask: Default::default(),
197             restorer: Default::default(),
198         }
199     }
200 }
201 
202 impl Sigaction {
203     /// 判断传入的信号是否被忽略
204     ///
205     /// ## 参数
206     ///
207     /// - `sig` 传入的信号
208     ///
209     /// ## 返回值
210     ///
211     /// - `true` 被忽略
212     /// - `false`未被忽略
213     pub fn is_ignore(&self) -> bool {
214         return self.action.is_ignore();
215     }
216     pub fn new(
217         action: SigactionType,
218         flags: SigFlags,
219         mask: SigSet,
220         restorer: Option<VirtAddr>,
221     ) -> Self {
222         Self {
223             action,
224             flags,
225             mask,
226             restorer,
227         }
228     }
229 
230     pub fn action(&self) -> SigactionType {
231         self.action
232     }
233 
234     pub fn flags(&self) -> SigFlags {
235         self.flags
236     }
237 
238     pub fn restorer(&self) -> Option<VirtAddr> {
239         self.restorer
240     }
241 
242     pub fn flags_mut(&mut self) -> &mut SigFlags {
243         &mut self.flags
244     }
245 
246     pub fn set_action(&mut self, action: SigactionType) {
247         self.action = action;
248     }
249 
250     pub fn mask(&self) -> SigSet {
251         self.mask
252     }
253 
254     pub fn mask_mut(&mut self) -> &mut SigSet {
255         &mut self.mask
256     }
257 
258     pub fn set_restorer(&mut self, restorer: Option<VirtAddr>) {
259         self.restorer = restorer;
260     }
261 
262     /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
263     pub const DEFAULT_SIGACTION: Sigaction = Sigaction {
264         action: SigactionType::SaHandler(SaHandlerType::Default),
265         flags: SigFlags::empty(),
266         mask: SigSet::from_bits_truncate(0),
267         restorer: None,
268     };
269 
270     /// 默认的“忽略信号”的sigaction
271     pub const DEFAULT_SIGACTION_IGNORE: Sigaction = Sigaction {
272         action: SigactionType::SaHandler(SaHandlerType::Ignore),
273         flags: SigFlags::empty(),
274         mask: SigSet::from_bits_truncate(0),
275         restorer: None,
276     };
277 }
278 
279 /// 用户态传入的sigaction结构体(符合posix规范)
280 /// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
281 #[repr(C)]
282 #[derive(Debug, Clone, Copy)]
283 pub struct UserSigaction {
284     pub handler: *mut core::ffi::c_void,
285     pub flags: SigFlags,
286     pub restorer: *mut core::ffi::c_void,
287     pub mask: SigSet,
288 }
289 
290 /**
291  * siginfo中,根据signal的来源不同,该info中对应了不同的数据./=
292  * 请注意,该info最大占用16字节
293  */
294 
295 #[repr(C)]
296 #[derive(Copy, Clone, Debug)]
297 pub struct SigInfo {
298     sig_no: i32,
299     sig_code: SigCode,
300     errno: i32,
301     sig_type: SigType,
302 }
303 
304 impl SigInfo {
305     pub fn sig_code(&self) -> SigCode {
306         self.sig_code
307     }
308 
309     pub fn set_sig_type(&mut self, sig_type: SigType) {
310         self.sig_type = sig_type;
311     }
312     /// @brief 将siginfo结构体拷贝到用户栈
313     /// ## 参数
314     ///
315     /// `to` 用户空间指针
316     ///
317     /// ## 注意
318     ///
319     /// 该函数对应Linux中的https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c#3323
320     /// Linux还提供了 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/signal.c#3383 用来实现
321     /// kernel_siginfo 保存到 用户的 compact_siginfo 的功能,但是我们系统内还暂时没有对这两种
322     /// siginfo做区分,因此暂时不需要第二个函数
323     pub fn copy_siginfo_to_user(&self, to: *mut SigInfo) -> Result<i32, SystemError> {
324         // 验证目标地址是否为用户空间
325         let mut user_buffer = UserBufferWriter::new(to, size_of::<SigInfo>(), true)?;
326 
327         let retval: Result<i32, SystemError> = Ok(0);
328 
329         user_buffer.copy_one_to_user(self, 0)?;
330         return retval;
331     }
332 }
333 
334 #[derive(Copy, Clone, Debug)]
335 pub enum SigType {
336     Kill(Pid),
337     Alarm(Pid),
338     // 后续完善下列中的具体字段
339     // Timer,
340     // Rt,
341     // SigChild,
342     // SigFault,
343     // SigPoll,
344     // SigSys,
345 }
346 
347 impl SigInfo {
348     pub fn new(sig: Signal, sig_errno: i32, sig_code: SigCode, sig_type: SigType) -> Self {
349         Self {
350             sig_no: sig as i32,
351             sig_code,
352             errno: sig_errno,
353             sig_type,
354         }
355     }
356 }
357 
358 #[derive(Debug, Default)]
359 pub struct SigPending {
360     signal: SigSet,
361     queue: SigQueue,
362 }
363 
364 impl SigPending {
365     /// 判断是否有待处理的信号
366     pub fn has_pending(&self) -> bool {
367         return !self.signal.is_empty();
368     }
369 
370     pub fn signal(&self) -> SigSet {
371         self.signal
372     }
373 
374     pub fn queue(&self) -> &SigQueue {
375         &self.queue
376     }
377 
378     pub fn queue_mut(&mut self) -> &mut SigQueue {
379         &mut self.queue
380     }
381 
382     pub fn signal_mut(&mut self) -> &mut SigSet {
383         &mut self.signal
384     }
385     /// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高)
386     ///
387     /// @param pending 等待处理的信号
388     /// @param sig_mask 屏蔽了的信号
389     /// @return i32 下一个要处理的信号的number. 如果为0,则无效
390     pub fn next_signal(&self, sig_mask: &SigSet) -> Signal {
391         let mut sig = Signal::INVALID;
392 
393         let s = self.signal();
394         let m = *sig_mask;
395         m.is_empty();
396         // 获取第一个待处理的信号的号码
397         let x = s & (!m);
398         if x.bits() != 0 {
399             sig = Signal::from(ffz(x.complement().bits()) + 1);
400             return sig;
401         }
402 
403         // 暂时只支持64种信号
404         assert_eq!(MAX_SIG_NUM, 64);
405 
406         return sig;
407     }
408     /// @brief 收集信号的信息
409     ///
410     /// @param sig 要收集的信号的信息
411     /// @param pending 信号的排队等待标志
412     /// @return SigInfo 信号的信息
413     pub fn collect_signal(&mut self, sig: Signal) -> SigInfo {
414         let (info, still_pending) = self.queue_mut().find_and_delete(sig);
415 
416         // 如果没有仍在等待的信号,则清除pending位
417         if !still_pending {
418             self.signal_mut().remove(sig.into());
419         }
420 
421         if let Some(info) = info {
422             return info;
423         } else {
424             // 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。
425             let mut ret = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(Pid::from(0)));
426             ret.set_sig_type(SigType::Kill(Pid::new(0)));
427             return ret;
428         }
429     }
430 
431     /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
432     /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
433     pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
434         // debug!("dequeue signal");
435         // 获取下一个要处理的信号的编号
436         let sig = self.next_signal(sig_mask);
437 
438         let info: Option<SigInfo> = if sig != Signal::INVALID {
439             // 如果下一个要处理的信号是合法的,则收集其siginfo
440             Some(self.collect_signal(sig))
441         } else {
442             None
443         };
444 
445         // 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
446         // recalc_sigpending();
447         return (sig, info);
448     }
449     /// @brief 从sigpending中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
450     pub fn flush_by_mask(&mut self, mask: &SigSet) {
451         // 定义过滤器,从sigqueue中删除mask中被置位的信号
452         let filter = |x: &SigInfo| !mask.contains(SigSet::from_bits_truncate(x.sig_no as u64));
453         self.queue.q.retain(filter);
454     }
455 }
456 
457 /// @brief 进程接收到的信号的队列
458 #[derive(Debug, Clone, Default)]
459 pub struct SigQueue {
460     pub q: Vec<SigInfo>,
461 }
462 
463 #[allow(dead_code)]
464 impl SigQueue {
465     /// @brief 初始化一个新的信号队列
466     pub fn new(capacity: usize) -> Self {
467         SigQueue {
468             q: Vec::with_capacity(capacity),
469         }
470     }
471 
472     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
473     ///
474     /// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
475     pub fn find(&self, sig: Signal) -> (Option<&SigInfo>, bool) {
476         // 是否存在多个满足条件的siginfo
477         let mut still_pending = false;
478         let mut info: Option<&SigInfo> = None;
479 
480         for x in self.q.iter() {
481             if x.sig_no == sig as i32 {
482                 if info.is_some() {
483                     still_pending = true;
484                     break;
485                 } else {
486                     info = Some(x);
487                 }
488             }
489         }
490         return (info, still_pending);
491     }
492 
493     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
494     ///
495     /// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
496     pub fn find_and_delete(&mut self, sig: Signal) -> (Option<SigInfo>, bool) {
497         // 是否存在多个满足条件的siginfo
498         let mut still_pending = false;
499         let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
500 
501         let filter = |x: &mut SigInfo| {
502             if x.sig_no == sig as i32 {
503                 if !first {
504                     // 如果之前已经筛选出了一个元素,则不把当前元素删除
505                     still_pending = true;
506                     return false;
507                 } else {
508                     // 当前是第一个被筛选出来的元素
509                     first = false;
510                     return true;
511                 }
512             }
513             return false;
514         };
515         // 从sigqueue中过滤出结果
516         let mut filter_result: Vec<SigInfo> = self.q.extract_if(filter).collect();
517         // 筛选出的结果不能大于1个
518         assert!(filter_result.len() <= 1);
519 
520         return (filter_result.pop(), still_pending);
521     }
522 
523     /// @brief 从C的void*指针转换为static生命周期的可变引用
524     pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue {
525         let sq = p as *mut SigQueue;
526         let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
527         return sq;
528     }
529 }
530 
531 ///
532 /// 定义了不同架构下实现 Signal 要实现的接口
533 ///
534 pub trait SignalArch {
535     /// 信号处理函数
536     ///
537     /// ## 参数
538     ///
539     /// - `frame` 中断栈帧
540     unsafe fn do_signal(frame: &mut TrapFrame);
541 
542     fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64;
543 }
544