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