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