1use core::ffi::c_void;
2use core::hint::unreachable_unchecked;
3use core::mem::MaybeUninit;
4
5use sc::syscall;
6
7use crate::platform::{NonNegativeI32, SaMask, SigSetT, SIG_DFL, SIG_IGN};
8
9#[repr(C)]
11#[expect(clippy::struct_field_names)]
12struct Sigaction {
13 sa_sigaction: SaSigaction,
15 sa_flags: i32,
16 sa_restorer: unsafe extern "C" fn() -> !,
19 sa_mask: SigSetT,
20}
21
22#[repr(C)]
26#[derive(Copy, Clone)]
27union SaSigaction {
28 value: usize,
29 sa_handler: unsafe extern "C" fn(i32),
30 sa_sigaction: unsafe extern "C" fn(i32, info: *mut SigInfo, *const c_void),
31}
32
33#[derive(Debug, Copy, Clone)]
34pub enum SaSignalaction {
35 Dfl,
36 Ign,
37 Handler(unsafe extern "C" fn(i32)),
38 SigAction(unsafe extern "C" fn(i32, info: *mut SigInfo, *const c_void)),
39}
40
41#[repr(C)]
42pub struct SigInfo {
43 pub si_signo: i32,
44 pub si_errno: i32,
45 pub si_code: i32,
46 pub si_trapno: i32,
47 pub si_pid: i32,
48 _pad: [i32; 27],
49 _align: [u64; 0],
50}
51
52unsafe extern "C" fn restorer() -> ! {
54 syscall!(RT_SIGRETURN);
55 unreachable_unchecked()
56}
57
58pub enum CatchSignal {
63 Int,
65 Term,
67 Hup,
69 Segv,
71 Chld,
73}
74
75impl CatchSignal {
76 fn into_raw(self) -> NonNegativeI32 {
77 match self {
78 CatchSignal::Int => crate::platform::SignalKind::SIGINT.0,
79 CatchSignal::Term => crate::platform::SignalKind::SIGTERM.0,
80 CatchSignal::Hup => crate::platform::SignalKind::SIGHUP.0,
81 CatchSignal::Segv => crate::platform::SignalKind::SIGSEGV.0,
82 CatchSignal::Chld => crate::platform::SignalKind::SIGCHLD.0,
83 }
84 }
85}
86
87#[expect(clippy::cast_possible_truncation)]
96pub unsafe fn add_signal_action(
97 signal: CatchSignal,
98 sigaction: SaSignalaction,
99) -> crate::error::Result<()> {
100 let mut constructed_action: MaybeUninit<Sigaction> = MaybeUninit::uninit();
101 let mut flags = SaMask::SA_RESTART | SaMask::SA_RESTORER;
102 let s_ptr = constructed_action.as_mut_ptr();
103 (*s_ptr).sa_mask = SigSetT::default();
104 (*s_ptr).sa_restorer = restorer;
105 (*s_ptr).sa_sigaction = match sigaction {
106 SaSignalaction::Dfl => SaSigaction { value: SIG_DFL },
107 SaSignalaction::Ign => SaSigaction { value: SIG_IGN },
108 SaSignalaction::Handler(sa_handler) => {
109 flags = SaMask(flags.bits() - SaMask::SA_SIGINFO.bits());
111 SaSigaction { sa_handler }
112 }
113 SaSignalaction::SigAction(sa_sigaction) => {
114 flags |= SaMask::SA_SIGINFO;
115 SaSigaction { sa_sigaction }
116 }
117 };
118 (*s_ptr).sa_flags = flags.bits() as i32;
119 let res = syscall!(
120 RT_SIGACTION,
121 signal.into_raw().value(),
122 constructed_action.as_ptr(),
123 0,
124 8
125 );
126 bail_on_below_zero!(res, "`RT_SIGACTION` syscall failed");
127 Ok(())
128}