Skip to content

Commit c77e84c

Browse files
committed
feat: add rt_sigqueueinfo
1 parent 6149bc7 commit c77e84c

File tree

3 files changed

+75
-12
lines changed

3 files changed

+75
-12
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/src/imp/signal.rs

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::{mem, time::Duration};
22

3+
use alloc::sync::Arc;
34
use arceos_posix_api::ctypes::timespec;
45
use axerrno::{LinuxError, LinuxResult};
56
use axprocess::{Pid, Process, ProcessGroup, Thread};
@@ -70,6 +71,10 @@ fn check_sigset_size(size: usize) -> LinuxResult<()> {
7071
Ok(())
7172
}
7273

74+
fn parse_signo(signo: u32) -> LinuxResult<Signo> {
75+
Signo::from_repr(signo as u8).ok_or(LinuxError::EINVAL)
76+
}
77+
7378
pub fn sys_rt_sigprocmask(
7479
how: i32,
7580
set: UserConstPtr<SignalSet>,
@@ -103,14 +108,14 @@ pub fn sys_rt_sigprocmask(
103108
}
104109

105110
pub fn sys_rt_sigaction(
106-
signo: i32,
111+
signo: u32,
107112
act: UserConstPtr<kernel_sigaction>,
108113
oldact: UserPtr<kernel_sigaction>,
109114
sigsetsize: usize,
110115
) -> LinuxResult<isize> {
111116
check_sigset_size(sigsetsize)?;
112117

113-
let signo = Signo::from_repr(signo as u8).ok_or(LinuxError::EINVAL)?;
118+
let signo = parse_signo(signo)?;
114119
if matches!(signo, Signo::SIGKILL | Signo::SIGSTOP) {
115120
return Err(LinuxError::EINVAL);
116121
}
@@ -167,12 +172,12 @@ fn make_siginfo(signo: u32, code: u32) -> LinuxResult<Option<SignalInfo>> {
167172
if signo == 0 {
168173
return Ok(None);
169174
}
170-
let signo = Signo::from_repr(signo as u8).ok_or(LinuxError::EINVAL)?;
175+
let signo = parse_signo(signo)?;
171176
Ok(Some(SignalInfo::new(signo, code)))
172177
}
173178

174-
pub fn sys_kill(pid: i32, sig: u32) -> LinuxResult<isize> {
175-
let Some(sig) = make_siginfo(sig, SI_USER)? else {
179+
pub fn sys_kill(pid: i32, signo: u32) -> LinuxResult<isize> {
180+
let Some(sig) = make_siginfo(signo, SI_USER)? else {
176181
// TODO: should also check permissions
177182
return Ok(0);
178183
};
@@ -208,8 +213,8 @@ pub fn sys_kill(pid: i32, sig: u32) -> LinuxResult<isize> {
208213
Ok(result as isize)
209214
}
210215

211-
pub fn sys_tkill(tid: Pid, sig: u32) -> LinuxResult<isize> {
212-
let Some(sig) = make_siginfo(sig, SI_TKILL as u32)? else {
216+
pub fn sys_tkill(tid: Pid, signo: u32) -> LinuxResult<isize> {
217+
let Some(sig) = make_siginfo(signo, SI_TKILL as u32)? else {
213218
// TODO: should also check permissions
214219
return Ok(0);
215220
};
@@ -219,17 +224,62 @@ pub fn sys_tkill(tid: Pid, sig: u32) -> LinuxResult<isize> {
219224
Ok(0)
220225
}
221226

222-
pub fn sys_tgkill(tgid: Pid, tid: Pid, sig: u32) -> LinuxResult<isize> {
223-
let Some(sig) = make_siginfo(sig, SI_TKILL as u32)? else {
227+
pub fn sys_tgkill(tgid: Pid, tid: Pid, signo: u32) -> LinuxResult<isize> {
228+
let Some(sig) = make_siginfo(signo, SI_TKILL as u32)? else {
224229
// TODO: should also check permissions
225230
return Ok(0);
226231
};
227232

233+
send_signal_thread(get_thread_checked(tgid, tid)?.as_ref(), sig)?;
234+
Ok(0)
235+
}
236+
237+
fn get_thread_checked(tgid: Pid, tid: Pid) -> LinuxResult<Arc<Thread>> {
228238
let thr = get_thread(tid)?;
229239
if thr.process().pid() != tgid {
230240
return Err(LinuxError::ESRCH);
231241
}
232-
send_signal_thread(&thr, sig)?;
242+
Ok(thr)
243+
}
244+
245+
fn make_queue_signal_info(
246+
tgid: Pid,
247+
signo: u32,
248+
sig: UserConstPtr<SignalInfo>,
249+
) -> LinuxResult<SignalInfo> {
250+
let signo = parse_signo(signo)?;
251+
let mut sig = unsafe { sig.get()?.read() };
252+
sig.set_signo(signo);
253+
if sig.code() != SI_USER && current().task_ext().thread.process().pid() != tgid {
254+
return Err(LinuxError::EPERM);
255+
}
256+
Ok(sig)
257+
}
258+
259+
pub fn sys_rt_sigqueueinfo(
260+
tgid: Pid,
261+
signo: u32,
262+
sig: UserConstPtr<SignalInfo>,
263+
sigsetsize: usize,
264+
) -> LinuxResult<isize> {
265+
check_sigset_size(sigsetsize)?;
266+
267+
let sig = make_queue_signal_info(tgid, signo, sig)?;
268+
send_signal_process(get_process(tgid)?.as_ref(), sig)?;
269+
Ok(0)
270+
}
271+
272+
pub fn sys_rt_tgsigqueueinfo(
273+
tgid: Pid,
274+
tid: Pid,
275+
signo: u32,
276+
sig: UserConstPtr<SignalInfo>,
277+
sigsetsize: usize,
278+
) -> LinuxResult<isize> {
279+
check_sigset_size(sigsetsize)?;
280+
281+
let sig = make_queue_signal_info(tgid, signo, sig)?;
282+
send_signal_thread(get_thread_checked(tgid, tid)?.as_ref(), sig)?;
233283
Ok(0)
234284
}
235285

@@ -262,7 +312,7 @@ pub fn sys_rt_sigtimedwait(
262312
};
263313

264314
if let Some(info) = info.nullable(UserPtr::get)? {
265-
sig.to_ctype(unsafe { &mut *info });
315+
unsafe { *info = sig.0 };
266316
}
267317

268318
Ok(0)

src/syscall.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,19 @@ fn handle_syscall(tf: &mut TrapFrame, syscall_num: usize) -> isize {
135135
Sysno::kill => sys_kill(tf.arg0() as _, tf.arg1() as _),
136136
Sysno::tkill => sys_tkill(tf.arg0() as _, tf.arg1() as _),
137137
Sysno::tgkill => sys_tgkill(tf.arg0() as _, tf.arg1() as _, tf.arg2() as _),
138+
Sysno::rt_sigqueueinfo => sys_rt_sigqueueinfo(
139+
tf.arg0() as _,
140+
tf.arg1() as _,
141+
tf.arg2().into(),
142+
tf.arg3() as _,
143+
),
144+
Sysno::rt_tgsigqueueinfo => sys_rt_tgsigqueueinfo(
145+
tf.arg0() as _,
146+
tf.arg1() as _,
147+
tf.arg2() as _,
148+
tf.arg3().into(),
149+
tf.arg4() as _,
150+
),
138151
Sysno::sigaltstack => sys_sigaltstack(tf.arg0().into(), tf.arg1().into()),
139152
_ => {
140153
warn!("Unimplemented syscall: {}", sysno);

0 commit comments

Comments
 (0)