starnix_core/signals/
signalfd.rs1use crate::signals::SignalDetail;
6use crate::task::{CurrentTask, EventHandler, WaitCanceler, Waiter};
7use crate::vfs::buffers::{InputBuffer, OutputBuffer};
8use crate::vfs::{
9 Anon, FileHandle, FileObject, FileOps, fileops_impl_nonseekable, fileops_impl_noop_sync,
10};
11use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Mutex};
12use starnix_uapi::errors::Errno;
13use starnix_uapi::open_flags::OpenFlags;
14use starnix_uapi::signals::SigSet;
15use starnix_uapi::vfs::FdEvents;
16use starnix_uapi::{SFD_NONBLOCK, errno, error, signalfd_siginfo};
17use zerocopy::IntoBytes;
18
19pub struct SignalFd {
20 mask: Mutex<SigSet>,
21}
22
23impl SignalFd {
24 pub fn new_file<L>(
25 locked: &mut Locked<L>,
26 current_task: &CurrentTask,
27 mask: SigSet,
28 flags: u32,
29 ) -> FileHandle
30 where
31 L: LockEqualOrBefore<FileOpsCore>,
32 {
33 let mut open_flags = OpenFlags::RDONLY;
34 if flags & SFD_NONBLOCK != 0 {
35 open_flags |= OpenFlags::NONBLOCK;
36 }
37 Anon::new_private_file(
38 locked,
39 current_task,
40 Box::new(SignalFd { mask: Mutex::new(mask) }),
41 open_flags,
42 "[signalfd]",
43 )
44 }
45
46 pub fn set_mask(&self, mask: SigSet) {
47 *self.mask.lock() = mask;
48 }
49}
50
51impl FileOps for SignalFd {
52 fileops_impl_nonseekable!();
53 fileops_impl_noop_sync!();
54
55 fn read(
56 &self,
57 locked: &mut Locked<FileOpsCore>,
58 file: &FileObject,
59 current_task: &CurrentTask,
60 offset: usize,
61 data: &mut dyn OutputBuffer,
62 ) -> Result<usize, Errno> {
63 debug_assert!(offset == 0);
64 file.blocking_op(locked, current_task, FdEvents::POLLIN | FdEvents::POLLHUP, None, |_| {
65 let mask = *self.mask.lock();
66 let data_len = data.available();
67 let mut buf = Vec::new();
68 while buf.len() + std::mem::size_of::<signalfd_siginfo>() <= data_len {
69 let signal = current_task
70 .write()
71 .take_signal_with_mask(!mask)
72 .ok_or_else(|| errno!(EAGAIN))?;
73 let mut siginfo = signalfd_siginfo {
74 ssi_signo: signal.signal.number(),
75 ssi_errno: signal.errno,
76 ssi_code: signal.code,
77 ..Default::default()
78 };
79 match signal.detail {
82 SignalDetail::None => {}
83 SignalDetail::Kill { pid, uid } => {
84 siginfo.ssi_pid = pid as u32;
85 siginfo.ssi_uid = uid;
86 }
87 SignalDetail::SIGCHLD { pid, uid, status } => {
88 siginfo.ssi_pid = pid as u32;
89 siginfo.ssi_uid = uid;
90 siginfo.ssi_status = status;
91 }
92 SignalDetail::SigFault { addr } => {
93 siginfo.ssi_addr = addr;
94 }
95 SignalDetail::SIGSYS { call_addr, syscall, arch } => {
96 siginfo.ssi_call_addr = call_addr.into();
97 siginfo.ssi_syscall = syscall;
98 siginfo.ssi_arch = arch;
99 }
100 SignalDetail::Raw { data } => {
101 siginfo.ssi_uid = u32::from_ne_bytes(data[4..8].try_into().unwrap());
105 siginfo.ssi_pid = u32::from_ne_bytes(data[0..4].try_into().unwrap());
106 siginfo.ssi_fd = i32::from_ne_bytes(data[8..12].try_into().unwrap());
107 siginfo.ssi_tid = u32::from_ne_bytes(data[0..4].try_into().unwrap());
108 siginfo.ssi_band = u32::from_ne_bytes(data[0..4].try_into().unwrap());
109 siginfo.ssi_overrun = u32::from_ne_bytes(data[4..8].try_into().unwrap());
110 siginfo.ssi_status = i32::from_ne_bytes(data[8..12].try_into().unwrap());
111 siginfo.ssi_int = i32::from_ne_bytes(data[8..12].try_into().unwrap());
112 siginfo.ssi_ptr = u64::from_ne_bytes(data[8..16].try_into().unwrap());
113 siginfo.ssi_addr = u64::from_ne_bytes(data[0..8].try_into().unwrap());
114 siginfo.ssi_syscall = i32::from_ne_bytes(data[8..12].try_into().unwrap());
115 siginfo.ssi_call_addr = u64::from_ne_bytes(data[0..8].try_into().unwrap());
116 siginfo.ssi_arch = u32::from_ne_bytes(data[12..16].try_into().unwrap());
117 siginfo.ssi_utime = u64::from_ne_bytes(data[12..20].try_into().unwrap());
118 siginfo.ssi_stime = u64::from_ne_bytes(data[20..28].try_into().unwrap());
119 }
120 SignalDetail::Timer { timer } => {
121 siginfo.ssi_tid = timer.timer_id as u32;
122 siginfo.ssi_overrun = timer.overrun_cur() as u32;
123 siginfo.ssi_int = timer.signal_event.value.0 as i32;
124 siginfo.ssi_ptr = timer.signal_event.value.0;
125 }
126 }
127 buf.extend_from_slice(siginfo.as_bytes());
128 }
129 data.write_all(&buf)
130 })
131 }
132
133 fn wait_async(
134 &self,
135 _locked: &mut Locked<FileOpsCore>,
136 _file: &FileObject,
137 current_task: &CurrentTask,
138 waiter: &Waiter,
139 _events: FdEvents,
140 handler: EventHandler,
141 ) -> Option<WaitCanceler> {
142 let mask = *self.mask.lock();
143 Some(current_task.read().wait_on_signal_fd_events(waiter, mask, handler))
144 }
145
146 fn query_events(
147 &self,
148 _locked: &mut Locked<FileOpsCore>,
149 _file: &FileObject,
150 current_task: &CurrentTask,
151 ) -> Result<FdEvents, Errno> {
152 let mut events = FdEvents::empty();
153 if current_task.read().is_any_signal_allowed_by_mask(!*self.mask.lock()) {
154 events |= FdEvents::POLLIN;
155 }
156 Ok(events)
157 }
158
159 fn write(
160 &self,
161 _locked: &mut Locked<FileOpsCore>,
162 _file: &FileObject,
163 _current_task: &CurrentTask,
164 offset: usize,
165 _data: &mut dyn InputBuffer,
166 ) -> Result<usize, Errno> {
167 debug_assert!(offset == 0);
168 error!(EINVAL)
169 }
170}