1use axerrno::{LinuxError, LinuxResult};
2use axhal::{
3 arch::TrapFrame,
4 trap::{POST_TRAP, register_trap_handler},
5};
6use axprocess::{Process, ProcessGroup, Thread};
7use axsignal::{SignalInfo, SignalOSAction, SignalSet};
8use axtask::{TaskExtRef, current};
9use starry_core::task::{ProcessData, ThreadData};
10
11use crate::do_exit;
12
13pub fn check_signals(tf: &mut TrapFrame, restore_blocked: Option<SignalSet>) -> bool {
14 let Some((sig, os_action)) = current()
15 .task_ext()
16 .thread_data()
17 .signal
18 .check_signals(tf, restore_blocked)
19 else {
20 return false;
21 };
22
23 let signo = sig.signo();
24 match os_action {
25 SignalOSAction::Terminate => {
26 do_exit(128 + signo as i32, true);
27 }
28 SignalOSAction::CoreDump => {
29 do_exit(128 + signo as i32, true);
31 }
32 SignalOSAction::Stop => {
33 do_exit(1, true);
35 }
36 SignalOSAction::Continue => {
37 }
39 SignalOSAction::Handler => {
40 }
42 }
43 true
44}
45
46#[register_trap_handler(POST_TRAP)]
47fn post_trap_callback(tf: &mut TrapFrame, from_user: bool) {
48 if !from_user {
49 return;
50 }
51
52 check_signals(tf, None);
53}
54
55pub fn send_signal_thread(thr: &Thread, sig: SignalInfo) -> LinuxResult<()> {
56 info!("Send signal {:?} to thread {}", sig.signo(), thr.tid());
57 let Some(thr) = thr.data::<ThreadData>() else {
58 return Err(LinuxError::EPERM);
59 };
60 thr.signal.send_signal(sig);
61 Ok(())
62}
63
64pub fn send_signal_process(proc: &Process, sig: SignalInfo) -> LinuxResult<()> {
65 info!("Send signal {:?} to process {}", sig.signo(), proc.pid());
66 let Some(proc) = proc.data::<ProcessData>() else {
67 return Err(LinuxError::EPERM);
68 };
69 proc.signal.send_signal(sig);
70 Ok(())
71}
72
73pub fn send_signal_process_group(pg: &ProcessGroup, sig: SignalInfo) -> usize {
74 info!(
75 "Send signal {:?} to process group {}",
76 sig.signo(),
77 pg.pgid()
78 );
79 let mut count = 0;
80 for proc in pg.processes() {
81 count += send_signal_process(&proc, sig.clone()).is_ok() as usize;
82 }
83 count
84}