starry_api/
signal.rs

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            // TODO: implement core dump
30            do_exit(128 + signo as i32, true);
31        }
32        SignalOSAction::Stop => {
33            // TODO: implement stop
34            do_exit(1, true);
35        }
36        SignalOSAction::Continue => {
37            // TODO: implement continue
38        }
39        SignalOSAction::Handler => {
40            // do nothing
41        }
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}